AT TINY13A


The ATTiny13 series chips are extremely cheap and useful for small projects that don't need a the full  capabilities of the larger, more expensive microcontrollers such as the Arduino.

 

The ATtiny13 is a low-power CMOS 8-bit microcontroller based on the AVR enhanced RISC architecture. By executing powerful instructions in a single clock cycle, the ATtiny13 achieves throughputs approaching 1 MIPS per MHz allowing the system designer to optimize power consumption versus processing speed.


To program the ATTiny, it is quite straightforward to set up an Arduino board as an AVRISP (AVR is a family of microcontrollers and ISP means In System Programmer). Firstly, the Arduino IDE needs to be configured. The Arduino IDE can be download from here: https://www.arduino.cc/en/main/software

 

Once installed, the first thing to do is to turn the Arduino into an ISP. Open the Arduino IDE and select File -> Examples -> 11.ArduinoISP ->ArduinoISP and upload this to an Arduino board.

 


The hardware package for the ATTiny 13 has to be installed. Select File -> Preferences go to Additional Boards Manager URLs and passte the following into the box:

 

https://mcudude.github.io/MicroCore/package_MCUdude_MicroCore_index.json

 

Click “OK” to save the settings.

                           


Next, open Tools -> Board -> Boards manager. Find MicroCore and click OK to  install it.

 

Now connect the ATTiny 13A to the Arduino. Connect the pins as follows:

 

ATTiny13A                         Arduino

pin 1                                   pin 10

pin 5                                   pin 11

pin 6                                   pin 12

pin 7                                   pin 13

pin 8                                   5v

pin 4                                   Ground (GND)

 

Here is a schematic of the ATTiny 13A chip pinouts.

 

 

You will find it easier to connect the ATTiny pins to the Arduino pins via a breadboard. To set up the ATTiny in the Arduino IDE, select “Tools” and select the following:

 

Board: ATtiny 13

BOD: 2.7v 

Clock: 9.6 MHz internal osc.

Compiler LTO: Enable

Port: (Your Arduino port)

Programmer: Arduino as ISP

 

Finally, you will need to burn Bootloader ((You only need to do this once per chip)

 

In the Arduino IDE, select “Tools”, “Burn Bootloader”.You might see an error, but ignore it.

 

The ATTiny is now ready to receive programs via the Arduino. This can be done by writing/compiling the program (sketch) in the Arduino IDE and then selecting “Sketch”, “Upload Using Programmer”. There follows a series of experiments with the ATTiny (ATTiny 13A is used throughout) that will illustrate some of it’s capabilities. These can be adapted and incorporated into a huge range of applications. The ATTiny will needed to be connected to the Arduino ISP to enable it to receive each program (sketch). Note that this setup, or “core” is used in all the examples up to the section “Serial Communication”. That section describes the setting up of a different core. The subsequent examples that appear use that new core.



Below is a list of links to various topics and applications.


Core 1

Blink LED 
Fade LED 20
Traffic Light Display Module 21
RGB LED 22
Basic Buzzer 25
Buzzer Tone Generator 25
Piezoelectric Speaker 28
Tilt Sensor 31
PIR Motion Detector 32
Reed Sensor 33
Hall Effect Sensor 34
Capacitive Touch Sensor 35
Push Button Switch 36
Stepper Motor with ULN2003 Driver 38
Shift Register 74HC595N 40
Line Decoder SN74HCT138N 47

Core 2 

Serial Communication 52
Serial Menu 53
Read Serial ASCII String 55
Serial Digital Clock 56
Random Number Generator 58
Physical Pixel 59
Randomly flashing LED with PRNG 60
Temperature Sensor 62
TM1637 Seven Segment Display 63
TM1637 Seven Segment Display With Library. 72
DHT-11 Temperature and Humidity Sensor 73
Light Sensor 76
Sound Sensor 78
Flame Detection Sensor 80
Soil Moisture Sensor 82
Ultrasound Distance Measurement 83
Potentiometer 86
Data Logging: MakerPlot 87
NE555 Frequency Adjustable Pulse Generator 90
LM386 Mono Class D Amplifier 92
Nokia 5110 LCD Display 94

 

Blink LED

This example will instruct the ATTiny to turn an LED on and off at a pre-determined frequency.

 

Add an LED to pin 3 (PB4) of the ATTiny. The longer leg of the LED to this pin and the shorter leg to Ground (GND). Copy the following sketch and paste it into the Arduino IDE. Select “Sketch”, “Upload Using Programmer”.

 

void setup() {

 // initialize pin 3 (ATtiny PB4, leg 3) as an output.

 pinMode(4, OUTPUT);

}

void loop() {

 digitalWrite(4, HIGH);   // turn the LED on (HIGH is the voltage level)

 delay(1000);             // wait for a second

 digitalWrite(4, LOW);    // turn the LED off by making the voltage LOW

 delay(1000);             // wait for a second

}

 

The LED should turn off and on every 1000 milliseconds (1 second). The program is easily adapted to alter the frequency of the turning the LED on and off. This is done by simply changing the delay() value.

 


Fade LED

Rather than just turn an LED on and off, this example will instruct the ATTiny to fade an LED on and off at a pre-determined frequency. Attach an LED to PB0 pin, leg 5 of the Attiny, the longer leg of the LED to this pin and the shorter leg to Ground (GND). Upload the following program:

 

#include <avr/io.h>

#include <util/delay.h>

// initialize ATtiny PB0 pin, (leg 5) as an output

#define LED_PIN         PB0

//#define LED_PIN         4

#define DELAY_MAX       (512)

#define DELAY_MIN       (1)

 

#if DELAY_MAX < 1 || DELAY_MIN < 1

# warning "Value of DELAY_MAX and DELAY_MAIN should be from range <1, 2^16>"

#endif

#if !(DELAY_MAX > DELAY_MIN)

# warning "Value of DELAY_MAX should be greater then DELAY_MIN"

#endif

int

main(void)

{

        uint16_t delay = DELAY_MIN;

        uint8_t dir = 0;

 

        /* setup */

        DDRB = 0b00000001; // set LED pin as OUTPUT

        PORTB = 0b00000001; // set LED pin to HIGH

 

        /* loop */

        while (1) {

 

                PORTB &= ~(_BV(LED_PIN)); // LED off

                _delay_loop_2(delay);

 

                PORTB |= _BV(LED_PIN); // LED on

                _delay_loop_2(DELAY_MAX - delay);

 

                if (dir) { // fade-in

                        if (++delay >= (DELAY_MAX - 1)) dir = 0;

                } else { // fade-out

                        if (--delay <= DELAY_MIN) dir = 1;

                }

        }

}

You should see the LED fadie between fully on and fully off.

Traffic Light Display Module

These small modules are designed for inclusion in model projects. As the name suggests, they can be used in projects and simulations involving traffic lights.

 

The module consists of three LEDs; red, yellow and green. You will need to connect these up to separate pins on the ATTiny so that you can make them turn on and off individually. In the example below, I have connected the LED pins as follows:

 

Green LED                         ATTiny pin 5  (PB0)

Yellow LED                       ATTiny pin 2  (PB3)

Red LED                            ATTiny pin 3  (PB4)

 

We need to decide on the sequence that the LEDs should turn on and off. This example scrolls through the LEDs in the following sequence: green, amber, red.

 

Connect the module to the ATTiny as described above and upload the following sketch:

 

void setup() {

 // initialize pin 0 (ATtiny leg 3) as an output.

 pinMode(0, OUTPUT);       //Green

 pinMode(3, OUTPUT);       //Amber

 pinMode(4, OUTPUT);       //Red

}

void loop() {

 digitalWrite(0, HIGH);   // turn the LED on (HIGH is the voltage level)

 delay(1000);             // wait for a second

 digitalWrite(0, LOW);    // turn the LED off by making the voltage LOW

 

 digitalWrite(3, HIGH);   // turn the LED on (HIGH is the voltage level)

 delay(1000);             // wait for a second

 digitalWrite(3, LOW);    // turn the LED off by making the voltage LOW

 

 digitalWrite(4, HIGH);   // turn the LED on (HIGH is the voltage level)

 delay(1000);             // wait for a second

 digitalWrite(4, LOW);    // turn the LED off by making the voltage LOW

 

}

You will see that the sequence is continuously followed and, as the sketch is a loop, the sequence will just continue to run and run.

 

By putting pauses (delay commands) between each step of the sequence, you can achieve a pretty good representation of real traffic lights.


RGB LED

The red, green, blue (RGB) LED has the ability to show a multitude of colours. As the name suggests, it can be red, green or blue, or any combination of these colours. This makes it very useful if we want to show different colours by using just one LED or show an unusual colour (not red, green, or blue). This type of LED has four pins; one for each of the three colours and one that is ground.

 

You will need to connect these module pins up to separate pins on the ATTiny so that you can make them turn on and off individually. In the example below, I have connected the LED pins as follows:

 

Green pin             ATTiny pin 5  (PB0)

Blue pin               ATTiny pin 2  (PB3)

Red pin                ATTiny pin 3  (PB4)

GND (Ground)    ATTiny pin 4

 

Connect the module to the ATTiny as described and upload the following sketch:

 

void setup() {

 // initialize pin 0 (ATtiny leg 3) as an output.

 pinMode(0, OUTPUT);       //Green

 pinMode(3, OUTPUT);       //Blue

 pinMode(4, OUTPUT);       //Red

}

void loop() {

 digitalWrite(0, HIGH);   // turn the LED on (HIGH is the voltage level)

 delay(1000);             // wait for a second

 digitalWrite(0, LOW);    // turn the LED off by making the voltage LOW

 

 digitalWrite(3, HIGH);   // turn the LED on (HIGH is the voltage level)

 delay(1000);             // wait for a second

 digitalWrite(3, LOW);    // turn the LED off by making the voltage LOW

 

 digitalWrite(4, HIGH);   // turn the LED on (HIGH is the voltage level)

 delay(1000);             // wait for a second

 digitalWrite(4, LOW);    // turn the LED off by making the voltage LOW

 

}

 

As with the earlier example of the Traffic Light Module, you will see a sequence of scrolling through the individual colours (red, green, blue).

 

There is a way of fading between colours with this module. The connections between the RGB module and the ATtiny are as follows:

 

Red pin                ATTiny pin 5  (PB0)

Green pin             ATTiny pin 6  (PB1)

Blue pin               ATTiny pin 7  (PB2)

GND (Ground)    ATTiny pin 4

 

Upload the following program to the ATTiny:

 

#include <avr/io.h>

#include <util/delay.h>

 

/* LED RBG pins */

#define    LED_RED      PB0

#define    LED_GREEN    PB1

#define    LED_BLUE     PB2

 

/* Rainbow settings */

#define    MAX        (512)

#define    STEP        (4)

 

/* Fading states */

#define    REDtoYELLOW    (0)

#define    YELLOWtoGREEN    (1)

#define    GREENtoCYAN    (2)

#define    CYANtoBLUE    (3)

#define    BLUEtoVIOLET    (4)

#define    VIOLETtoRED    (5)

 

/* Global variables */

uint16_t red = MAX;

uint16_t green = 0;

uint16_t blue = 0;

uint16_t state = 0;

 

void

rainbow(int n)

{

 

    switch (state) {

    case REDtoYELLOW: green += n; break;

    case YELLOWtoGREEN: red -= n; break;

    case GREENtoCYAN: blue += n; break;

    case CYANtoBLUE: green -= n; break;

    case BLUEtoVIOLET: red += n; break;

    case VIOLETtoRED: blue -= n; break;

    default: break;

    }

 

    if (red >= MAX || green >= MAX || blue >= MAX || red <= 0 || green <= 0 || blue <= 0) {

        state = (state + 1) % 6; // Finished fading a color so move on to the next

    }

}

 

int

main(void)

{

    uint16_t i = 0;

 

    /* --- setup --- */

   

    DDRB = 0b00000111;

    PORTB = 0b00000111;

 

    /* --- loop --- */

 

        while (1) {

 

        /* Rainbow algorithm */

 

        if (i < red) {

            PORTB &= ~(1 << LED_RED);

        } else {

             PORTB |= 1 << LED_RED;

        }

 

        if (i < green) {

            PORTB &= ~(1 << LED_GREEN);

        } else {

             PORTB |= 1 << LED_GREEN;

        }

 

        if (i < blue) {

            PORTB &= ~(1 << LED_BLUE);

        } else {

             PORTB |= 1 << LED_BLUE;

        }

 

        if (i >= MAX) {

            rainbow(STEP);

            i = 0;

        }

 

        i++;

    }

 

    return (0);

}


Basic Buzzer

This example will instruct the ATTiny to turn buzzer on and off at a pre-determined frequency, in this case every second.

 

Add a buzzer to pin 5 (PB0) of the ATTiny, one leg of the buzzer to this pin and other to Ground (GND). Copy the following sketch and paste it into the Arduino IDE. Select “sketch”, “Upload Using Programmer”.

 

void setup() {

 // initialize pin 0 (PB0, ATtiny leg 5) as an output.

 pinMode(0, OUTPUT);

}

void loop() {

 digitalWrite(0, HIGH);   // turn the BUZZER on (HIGH is the voltage level)

 delay(1000);             // wait for a second

 digitalWrite(0, LOW);    // turn the BUZZER off by making the voltage LOW

 delay(1000);             // wait for a second

}

 

The frequency of the turning the buzzer on and off can be altered by changing the value of the delay() function.

Buzzer Tone Generator

The following example generates a tone and is reproduced here by permission of it’s author, Łukasz Marcin Podkalicki.

 

/**

 * Copyright (c) 2016, Łukasz Marcin Podkalicki <lpodkalicki@gmail.com>

 * ATtiny13/015

 * Two-Tone Alarm.

 * --

 * Settings:

 *  FUSE_L=0x6A

 *  FUSE_H=0xFF

 *  F_CPU=1200000

 */

 

#include <avr/io.h>

#include <avr/interrupt.h>

#include <avr/pgmspace.h>

#include <util/delay.h>

 

#define    SPEAKER_PIN    PB0

 

#define    N_1    (_BV(CS00))

#define    N_8    (_BV(CS01))

#define    N_64   (_BV(CS01)|_BV(CS00))

#define    N_256  (_BV(CS02))

#define    N_1024 (_BV(CS02)|_BV(CS00))

 

static void twotone_alarm(uint8_t type);

static void tone_loop(uint8_t OCRxn, uint8_t N, uint8_t max, uint8_t delay, uint8_t pause, uint8_t fade);

static void timer_set(uint8_t OCRxn, uint8_t N);

static void sleep(uint8_t ms);

 

 

int

main(void)

{

 

    /* setup */

    DDRB |= _BV(SPEAKER_PIN); // set speaker pin as OUTPUT

    TCCR0A |= _BV(WGM01); // set timer mode to Fast PWM

    TCCR0A |= _BV(COM0A0); // connect PWM pin to Channel A of Timer0

 

    /* loop */

    while (1) {

        twotone_alarm(1);

    }

}

 

 

void

twotone_alarm(uint8_t type)

{

 

    switch(type) {

    /* Please, put here your own two-tone alarm composition! */

    case 1:

        tone_loop(123, N_8, 6, 10, 10, 1);

        tone_loop(22, N_8, 6, 10, 0, -1);

        break;

    default:

    case 0:

        tone_loop(32, N_8, 6, 10, 10, 1);

        tone_loop(22, N_8, 6, 10, 0, -1);

        break;

    }

}

 

 

/**

 * Single tone loop with fade-in/out effect.

 *

 * Base square wave frequency,

 * F = F_CPU / (2 * N * (1 + OCRnx)), where:

 * - F is a calculated PWM frequency

 * - F_CPU is a clock source (1.2MHz)

 * - the N variable represents the prescaler factor (1, 8, 64, 256, or 1024)

 *

 * @param OCRxn: timer OCRxn value

 * @param N: timer prescaler (N_1, N_8, N_64, N_256, N_1024)

 * @param max: number of iterations (incr/decr of OCRxn)

 * @param delay: little delay after each iteration in miliseconds

 * @param pause: delay after a tone loop, delay between tones

 * @param fade: fade-in (1) or fade-out (-1) factor

 */

void

tone_loop(uint8_t OCRxn, uint8_t N, uint8_t max, uint8_t delay, uint8_t pause, uint8_t fade)

{

    uint8_t i;

 

    for (i = 0; i < max; ++i) {

        timer_set(OCRxn, N);

        OCRxn += fade;

        sleep(delay);

    }

 

    sleep(pause);

}

 

void

timer_set(uint8_t OCRxn, uint8_t N)

{

 

    TCCR0B = (TCCR0B & ~((1<<CS02)|(1<<CS01)|(1<<CS00))) | N;

    OCR0A = OCRxn - 1;

}

 

void

sleep(uint8_t ms)

{

    uint8_t i;

 

    for (i = 0; i < ms; ++i) {

        _delay_ms(1);

    }

}

Piezoelectric Speaker

A piezoelectric speaker can play, as well as detect tones and can, with a little help, enable us to play actual melodies. By using the microcontroller’s capability of producing pulse width modulation (PWM) signals, we are able to alter the pitch of the sound. If you need to know more about PWM, details can be found here: http://webzone.k3.mah.se/k3dacu/projects/ivrea/motor/pwm.html

 

Here is a program that will play many tones (the same program that is featured earlier for the continuous buzzer). Attach red wire to pin 5 (PB0) of the ATTiny and the black wire to GND. Upload the following sketch using the Arduino ISP programmer.

 

#include <avr/io.h>

#include <avr/interrupt.h>

#include <avr/pgmspace.h>

#include <util/delay.h>

 

#define    SPEAKER_PIN    PB0 // pin 5 of the ATTiny

 

#define    N_1    (_BV(CS00))

#define    N_8    (_BV(CS01))

#define    N_64   (_BV(CS01)|_BV(CS00))

#define    N_256  (_BV(CS02))

#define    N_1024 (_BV(CS02)|_BV(CS00))

 

static void twotone_alarm(uint8_t type);

static void tone_loop(uint8_t OCRxn, uint8_t N, uint8_t max, uint8_t delay, uint8_t pause, uint8_t fade);

static void timer_set(uint8_t OCRxn, uint8_t N);

static void sleep(uint8_t ms);

 

int

main(void)

{

 

    /* setup */

    DDRB |= _BV(SPEAKER_PIN); // set speaker pin as OUTPUT

    TCCR0A |= _BV(WGM01); // set timer mode to Fast PWM

    TCCR0A |= _BV(COM0A0); // connect PWM pin to Channel A of Timer0

 

    /* loop */

    while (1) {

        twotone_alarm(1);

    }

}

void

twotone_alarm(uint8_t type)

{

 

    switch(type) {

 case 1:

        tone_loop(123, N_8, 6, 10, 10, 1);

        tone_loop(22, N_8, 6, 10, 0, -1);

        break;

    default:

    case 0:

        tone_loop(32, N_8, 6, 10, 10, 1);

        tone_loop(22, N_8, 6, 10, 0, -1);

        break;

    }

}

 

void

tone_loop(uint8_t OCRxn, uint8_t N, uint8_t max, uint8_t delay, uint8_t pause, uint8_t fade)

{

    uint8_t i;

 

    for (i = 0; i < max; ++i) {

        timer_set(OCRxn, N);

        OCRxn += fade;

        sleep(delay);

    }

 

    sleep(pause);

}

 

void

timer_set(uint8_t OCRxn, uint8_t N)

{

 

    TCCR0B = (TCCR0B & ~((1<<CS02)|(1<<CS01)|(1<<CS00))) | N;

    OCR0A = OCRxn - 1;

}

 

void

sleep(uint8_t ms)

{

    uint8_t i;

 

   for (i = 0; i < ms; ++i) {

        _delay_ms(1);

    }

}

 

By adding various delay commands and different notes you should be able to compose a simple melody. I’m sure that you will have hours of fun with this, whilst also gaining valuable experience by working with the program.


Tilt Sensor

A tilt sensor can be a useful component in numerous projects. Fixed to objects, it switches between two states if moved or tilted. The SW-520D is a simple ball tilt switch which has two pins. With the two pins level, a 10° tilt will close the contacts, thus altering the “state”.

 

As well as the sensor, we will also attach an LED so that we will have a visual indication of the sensors state. Firstly connect an LED to pin PB1 and (shortest leg) to GND  Connect one of the pins of the sensor to ground and the other pin to a 10k ohm pull up resistor and to ATTiny pin PB3.

 

Upload the following program (also available from

starter.html ):

 

const int sensorPin = PB3; 

const int ledPin = PB1;

int sensorState = 0;

 

void setup() {

 

pinMode(ledPin, OUTPUT);  // define LED pin as output

pinMode(sensorPin, INPUT);  // define sensor pin as output

}

 

void loop(){

sensorState = digitalRead(sensorPin); // state = value of the pin

if (sensorState == HIGH) {

digitalWrite(ledPin, HIGH);

}

else {digitalWrite(ledPin, LOW);}

 }

 

 

When the sensor is moved, its state will change from “LOW” to “HIGH”  and the light will flash correspondingly. Move the breadboard that is housing the tilt sensor to see this happening.

 

 

 


PIR Motion Detector

 

PIR motion detectors are widespread as they are used in many security systems to detect events such as trespass or other motion. The modules themselves are quite inexpensive and can be readily bought from numerous sources on the internet.

 

They have a range of detection of about 6–7m and are highly sensitive. When the PIR motion sensor detects motion, it outputs a 5V signal to the microcontroller and triggers an interrupt.  The required circuit is relatively simple:

 

Connect the input pin to ATTiny pin 2 (PB3), GND to GND and 5V to 5V. I have also added an LED to pin 6 (PB1), which has also been connected to GND.

 

Once the circuit is set up, construct a sketch similar to the one below ans upload it to the ATTiny using the ISP.

 

int ledPin = PB1;                             // the pin for the LED

int inputPin = PB3;                                          // input pin (for PIR sensor)

int pirState = LOW;                                       // we start, assuming no motion detected

int val = 0;                                       // variable for reading the pin status

 

void setup() {

  pinMode(ledPin, OUTPUT);         // declare LED as output

  pinMode(inputPin, INPUT);          // declare sensor as input

 

  );

}

 

void loop(){

  val = digitalRead(inputPin);          // read input value

  if (val == HIGH) {                                        // check if the input is HIGH

    digitalWrite(ledPin, HIGH);         // turn LED ON

    if (pirState == LOW) {                // we have just turned on

           pirState = HIGH;

    }

  } else {

    digitalWrite(ledPin, LOW);        // turn LED OFF

    if (pirState == HIGH){                // we have just turned off

      pirState = LOW;

    }

  }

}

 

If motion is detected the LED turns on. If no motion is detected, the LED remains turned off.

 

 


Reed Sensor

The Reed sensor module is also known as a magnetron module or reed switch. It is a small electrical switch operated by an applied magnetic field, commonly used as proximity sensor.

 

It has a working voltage 3.3V-5V, with a digital output which is capable of switching output (0 and 1).

 

This module can be incorporated into program-controlled switches, copiers, washing machines, refrigerators, cameras, electromagnetic relays, electronic weighing scales, level meters, gas meters, water meters and so on.

 

Connect D0 (digital out) of the Reed sensor module to pin 2 (PB3) of the ATTiny. Connect the VCC and GND to VCC and GND of the ATTiny. Connect an LED to pin 6 (PB1) of the ATTiny and the GND of the LED to GND of the ATTiny.

 

Once the circuit is set up, construct a sketch similar to the one below ans upload it to the ATTiny using the ISP.

 

int Reed = PB3;

int ledPin = PB1; 

int val ;

 

void setup (){

pinMode(ledPin, OUTPUT);// declare LED as output

pinMode (Reed, INPUT); // declare Reed as input

}

void loop (){

val = digitalRead (Reed) ;

 if (val == HIGH)  {

digitalWrite(ledPin, HIGH);  // turn LED ON}

  else

  {

   digitalWrite(ledPin, LOW);  // turn LED OFF

  }

    delay(2000);

}

 

When a magnet comes into close proximity of the circuit, the sensor will switch and the LED will turn on. This switching due to a magnetic field being present (or not) can be adapted and incorporated into larger projects.


Hall Effect Sensor

A Hall Effect sensor is a transducer that varies its output voltage in response to a magnetic field. Hall effect sensors are used for proximity switching, positioning, speed detection, and current sensing applications.

 

In a Hall Effect sensor, a thin strip of metal has a current applied along it. In the presence of a magnetic field, the electrons in the metal strip are deflected toward one edge, producing a voltage gradient across the short side of the strip (perpendicular to the feed current). Hall effect sensors have an advantage over inductive sensors in that, while inductive sensors respond to a changing magnetic field which induces current in a coil of wire and produces voltage at its output, Hall effect sensors can detect static (non-changing) magnetic fields.

 

Connect the VCC of the sensor to the 5V pin of the ATTiny. Connect GND to GND and connect the DO (digital out) of the sensor to  pin2 (PB3) of the ATTiny. Connect an LED to pin pin 6 (PB1) of the ATTiny. Once the circuit is set up, construct a sketch similar to the one below ans upload it to the ATTiny using the ISP.

 

int Hall = PB3;

int ledPin = PB1; 

int val ;

 

void setup ()

{

  pinMode(ledPin, OUTPUT);// declare LED as output

  pinMode (Hall, INPUT); // declare Reed as input

}

void loop ()

{

  val = digitalRead (Hall) ;

 

  if (val == HIGH)

  {

   digitalWrite(ledPin, HIGH);  // turn LED ON

  }

  else

  {

   digitalWrite(ledPin, LOW);  // turn LED OFF ie magnetic field detected

  }

    delay(100);

}

 

As the magnet gets nearer to the sensor (changing magnetic field), the digital value decreases and when the value reached “LOW”, the LED will turn off.

 

 


Capacitive Touch Sensor

The TTP233B capacitive touch sensor can be used as an alternative to the tactile push button switch in numerous applications. WIth the normal state, the module output is low and it has a low power consumption; When the sensor is touched,  , the module output state is high If it is not touched for 12 seconds,the  switch state changes to low. i.e.to low-power mode.The sensor requires a power supply of 2 ~ 5.5V DC.

 

The example below turns an LED on for a tenth of a second when the sensor is touched. Connect the VCC and GND of the module to VCC and GND (pins 8 and 4, respectively) of the ATTiny. Connect the I/O pin to pin 2 (PB3) of the ATTiny. Connect and LED to pin 6 (PB1) and ground. Upload the following sketch using the Arduino ISP programmer.

 

int sensor = PB3;

int ledPin = PB1;

 

int relay = 2;

 

boolean currentState = LOW;

boolean lastState = LOW;

boolean RelayState = LOW;

 

void setup() {

 

  pinMode(ledPin, OUTPUT); 

  pinMode(sensor, INPUT);

}

 

void loop() {

  currentState = digitalRead(sensor);

    if (currentState == HIGH && lastState == LOW){

    digitalWrite(ledPin, HIGH);  // turn LED ON

    delay(1);

   

    if (sensor == HIGH){

      digitalWrite(ledPin, LOW);

      RelayState = LOW;

    } else {

      digitalWrite(ledPin, HIGH);

      RelayState = HIGH;

      delay(100);

      digitalWrite(ledPin, LOW); //return LED to off

    }

  }

  lastState = currentState;

}


 Push Button Switch

 

Push button switches are easy to set up and can be used in innumerable situations. When pressed, they connect two points in a circuit. This basic example turns on an LED when the button is pressed. As well as breadboard, wires and the button itself, you will need a 10k ohm resistor.

 

 

The LED is attached to PB1 And the button attached to PB3. VCC and GND on the ATTiny are connected to VCC and GND on the breadboard.

 

Upload the following sketch using the Arduino ISP programmer.

.

const int buttonPin = PB3;    // the pushbutton pin

const int ledPin = PB1;        // the LED pin

 

// variables will change:

int buttonState = 0;        // variable for reading the pushbutton status

 

void setup() { 

pinMode(ledPin, OUTPUT);      // initialize the LED pin as an output

pinMode(buttonPin, INPUT);      // initialize the pushbutton pin as an input

}

 

void loop(){

buttonState = digitalRead(buttonPin);   // read the state of the pushbutton

 

//if pushbutton, the buttonState is HIGH:

 

 if (buttonState == HIGH) {

 

digitalWrite(ledPin, HIGH);       // turn LED on

}

 

else

 

{  digitalWrite(ledPin, LOW);       // turn LED off

}

 

}

 

 

This basic circuit and program can serve as part of much more complex projects. Try building a circuit that incorporates a push button (or more than one button) with an LED to turn several LEDs on and/or off. You can use other components and control them by push bouttons.

 


Stepper Motor with ULN2003 Driver

Stepper motors are used for position control. They divide a full rotation into a number of equal “steps” so can be programmed to move to specific positions. They are usually found in desktop printers, 3D printers, CNC to milling machines, and anything else that requires precise positioning control.

 

ULN2003 IC is one of the most commonly used Motor driver integrated circuits (IC) generally used when there is a need to drive high current loads using digital logic circuits like Timers, Gates, microcontrollers etc.

 

This example will show how to control a 28BYJ-48 stepper motor by using a ULN2003 driver board and ATTiny.

 

Usually, the 28BYJ-48 stepper motor comes with a 5-pin connector that will fit to the ULN2003 driver board .Connect the ULN2003 driver board to four digital pins on the ATTiny as follows:

 

ATTiny                ULN2003 Board

PB1                                    IN1

PB2                                    IN2

PB3                                    IN3

PB4                                     IN4

 

Upload the following sketch using the Arduino ISP programmer.

 

uint8_t wire1 = PB1;

uint8_t wire2 = PB2;

uint8_t wire3 = PB3;

uint8_t wire4 = PB4;

 

const uint16_t _delay = 50; /* delay in between two steps. minimum delay more the rotational speed */

 

void sequence(bool a, bool b, bool c, bool d){  /* four step sequence to stepper motor */

  digitalWrite(wire1, a);

  digitalWrite(wire2, b);

  digitalWrite(wire3, c);

  digitalWrite(wire4, d);

  delay(_delay);

}

 

void setup() {

  pinMode(wire1, OUTPUT); /* set four wires as output */

  pinMode(wire2, OUTPUT);

  pinMode(wire3, OUTPUT);

  pinMode(wire4, OUTPUT);

}

 

void loop() {

  /* Rotation in one direction */

  for(int i = 0; i<12; i++)

  {

    sequence(HIGH, LOW, LOW, LOW);

    sequence(HIGH, HIGH, LOW, LOW);

    sequence(LOW, HIGH, LOW, LOW);

    sequence(LOW, HIGH, HIGH, LOW);

    sequence(LOW, LOW, HIGH, LOW);

    sequence(LOW, LOW, HIGH, HIGH);

    sequence(LOW, LOW, LOW, HIGH);

    sequence(HIGH, LOW, LOW, HIGH);

  }

  sequence(HIGH, LOW, LOW, LOW);

  /* Rotation in opposite direction */

  for(int j = 0; j<12; j++)

  {

    sequence(LOW, LOW, LOW, HIGH);

    sequence(LOW, LOW, HIGH, HIGH);

    sequence(LOW, LOW, HIGH, LOW);

    sequence(LOW, HIGH, HIGH, LOW);

    sequence(LOW, HIGH, LOW, LOW);

    sequence(HIGH, HIGH, LOW, LOW);

    sequence(HIGH, LOW, LOW, LOW);

    sequence(HIGH, LOW, LOW, HIGH);

  }

  sequence(LOW, LOW, LOW, HIGH);

}

 

Once the program is uploaded and running you will see the stepper motor moving to different positions ansd in different directions. You can use this as a basis for other projects by altering the program to enable the stepper motor to perform specific movements.

 


Shift Register 74HC595N

A shift register is an integrated circuit that converts serial information to parallel. It requires 3 pins (as well as power and ground) from a microcontroller but allows us to have a total of 8 outputs. Earlier in this Section we have seen that we used one pin on the ATTiny to control one LED but by using a shift register, we can control 8 LEDs using only pins 3 pins.

 

 

The 74HC595 is a shift register which works on Serial IN Parallel OUT protocol. It receives data serially from the microcontroller and then sends out this data through parallel pins. The output pins can be increased by 8 using the single chip.

 

 

Earlier in this Section we used one pin on the ATTiny to control one LED but by using a shift register, we can control 8 LEDs using just 3 pins.. For illustration purposes, the examples below will use pins 5, 3 and 6 on the ATTiny to control the shift register. Pin PB0 is connected to the serial data pin, pin PB4 is connected to the clock pin and pin PB1 is connected to the latch pin.

The 8 LEDs are connected with their shorter legs (cathodes) to GND, whilst their longer legs (anodes) are connected to the shift register output pins (pins 1-7 and 15) via 220 ohm resistors. Pins 5, 6 and 3 (PB0, PB1 and PB4) of the ATTiny are connected to pins 14, 12 and 11 respectively of the 74HC595 shift register.

Counting

The first example counts from 0 to 255 and displays the number on the LEDs.

                   

//  Adapted from https://www.arduino.cc/en/tutorial/ShiftOut

 

int latchPin = PB1; //Pin connected to ST_CP of 74HC595

int clockPin = PB4;  //Pin connected to SH_CP of 74HC595

int dataPin = PB0; //Pin connected to DS of 74HC595

 

void setup() {

  //set pins to output so you can control the shift register

  pinMode(latchPin, OUTPUT);

  pinMode(clockPin, OUTPUT);

  pinMode(dataPin, OUTPUT);

}

 

void loop() {

  // count from 0 to 255 and display the number

  // on the LEDs

  for (int numberToDisplay = 0; numberToDisplay < 256; numberToDisplay++) {

    // take the latchPin low so

    // the LEDs don't change while you're sending in bits:

    digitalWrite(latchPin, LOW);

    // shift out the bits:

    shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay); 

 

    //take the latch pin high so the LEDs will light up:

    digitalWrite(latchPin, HIGH);

    // pause before next value:

    delay(500);

  }

}

 

Upload to the ATTiny using the programmer. You will see the LEDs turning on and off as the count goes from 0 to 256.

Using An Array

The second example uses an array to turn the LEDs on and off. The connections are as in the example above. Upload the following to the ATTiny using the programmer.

 

/*

  Shift Register Example

  Turning on the outputs of a 74HC595 using an array

 

 Hardware:

 * 74HC595 shift register

 * LEDs attached to each of the outputs of the shift register

 

 */

//Pin connected to ST_CP of 74HC595

int latchPin = PB1;

//Pin connected to SH_CP of 74HC595

int clockPin = PB4;

////Pin connected to DS of 74HC595

int dataPin = PB0;

 

//holders for infromation you're going to pass to shifting function

byte data;

byte dataArray[10];

 

void setup() {

  //set pins to output because they are addressed in the main loop

  pinMode(latchPin, OUTPUT);

  Serial.begin(9600);

 

  //Binary notation as comment

  dataArray[0] = 0xFF; //0b11111111

  dataArray[1] = 0xFE; //0b11111110

  dataArray[2] = 0xFC; //0b11111100

  dataArray[3] = 0xF8; //0b11111000

  dataArray[4] = 0xF0; //0b11110000

  dataArray[5] = 0xE0; //0b11100000

  dataArray[6] = 0xC0; //0b11000000

  dataArray[7] = 0x80; //0b10000000

  dataArray[8] = 0x00; //0b00000000

  dataArray[9] = 0xE0; //0b11100000

 

  //function that blinks all the LEDs

  //gets passed the number of blinks and the pause time

  blinkAll_2Bytes(2,500);

}

 

void loop() {

 

  for (int j = 0; j < 10; j++) {

    //load the light sequence you want from array

    data = dataArray[j];

    //ground latchPin and hold low for as long as you are transmitting

    digitalWrite(latchPin, 0);

    //move 'em out

    shiftOut(dataPin, clockPin, data);

    //return the latch pin high to signal chip that it

    //no longer needs to listen for information

    digitalWrite(latchPin, 1);

    delay(300);

  }

}

 

// the heart of the program

void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {

  // This shifts 8 bits out MSB first,

  //on the rising edge of the clock,

  //clock idles low

 

  //internal function setup

  int i=0;

  int pinState;

  pinMode(myClockPin, OUTPUT);

  pinMode(myDataPin, OUTPUT);

 

  //clear everything out just in case to

  //prepare shift register for bit shifting

  digitalWrite(myDataPin, 0);

  digitalWrite(myClockPin, 0);

 

  //for each bit in the byte myDataOut

  //NOTICE THAT WE ARE COUNTING DOWN in our for loop

  //This means that %00000001 or "1" will go through such

  //that it will be pin Q0 that lights.

  for (i=7; i>=0; i--)  {

    digitalWrite(myClockPin, 0);

 

    //if the value passed to myDataOut and a bitmask result

    // true then... so if we are at i=6 and our value is

    // %11010100 it would the code compares it to %01000000

    // and proceeds to set pinState to 1.

    if ( myDataOut & (1<<i) ) {

      pinState= 1;

    }

    else {

      pinState= 0;

    }

 

    //Sets the pin to HIGH or LOW depending on pinState

    digitalWrite(myDataPin, pinState);

    //register shifts bits on upstroke of clock pin 

    digitalWrite(myClockPin, 1);

    //zero the data pin after shift to prevent bleed through

    digitalWrite(myDataPin, 0);

  }

 

  //stop shifting

  digitalWrite(myClockPin, 0);

}

//blinks the whole register based on the number of times you want to

//blink "n" and the pause between them "d"

//starts with a moment of darkness to make sure the first blink

//has its full visual effect.

void blinkAll_2Bytes(int n, int d) {

  digitalWrite(latchPin, 0);

  shiftOut(dataPin, clockPin, 0);

  shiftOut(dataPin, clockPin, 0);

  digitalWrite(latchPin, 1);

  delay(200);

  for (int x = 0; x < n; x++) {

    digitalWrite(latchPin, 0);

    shiftOut(dataPin, clockPin, 255);

    shiftOut(dataPin, clockPin, 255);

    digitalWrite(latchPin, 1);

    delay(d);

    digitalWrite(latchPin, 0);

    shiftOut(dataPin, clockPin, 0);

    shiftOut(dataPin, clockPin, 0);

    digitalWrite(latchPin, 1);

    delay(d);

  }

}

Linking Shift Registers

To get even more outputs from the ATTiny, shift registers can be linked together.A second shift register can be connected to the first by connecting pin 9 (serial out)of the first to pin 14 (serial data input) of the second shift register. LEDs can be connected to the second shift register as illustrated in the previous examples.

 

Upload the following to the ATTiny using the programmer.

             

//Pin connected to ST_CP of 74HC595

int latchPin = PB1;

//Pin connected to SH_CP of 74HC595

int clockPin = PB4;

////Pin connected to DS of 74HC595

int dataPin = PB0;

 

void setup() {

  //Start Serial for debuging purposes 

  Serial.begin(9600);

  //set pins to output because they are addressed in the main loop

  pinMode(latchPin, OUTPUT);

 

}

 

void loop() {

  //count up routine

  for (int j = 0; j < 256; j++) {

    //ground latchPin and hold low for as long as you are transmitting

    digitalWrite(latchPin, 0);

    //count up on GREEN LEDs

    shiftOut(dataPin, clockPin, j);

    //count down on RED LEDs

    shiftOut(dataPin, clockPin, 255-j);

    //return the latch pin high to signal chip that it

    //no longer needs to listen for information

    digitalWrite(latchPin, 1);

    delay(1000);

  }

}

 

void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {

  // This shifts 8 bits out MSB first,

  //on the rising edge of the clock,

  //clock idles low

 

//internal function setup

  int i=0;

  int pinState;

  pinMode(myClockPin, OUTPUT);

  pinMode(myDataPin, OUTPUT);

 

 //clear everything out just in case to

 //prepare shift register for bit shifting

  digitalWrite(myDataPin, 0);

  digitalWrite(myClockPin, 0);

 

  //for each bit in the byte myDataOut

  //NOTICE THAT WE ARE COUNTING DOWN in our for loop

  //This means that %00000001 or "1" will go through such

  //that it will be pin Q0 that lights.

  for (i=7; i>=0; i--)  {

    digitalWrite(myClockPin, 0);

 

    //if the value passed to myDataOut and a bitmask result

    // true then... so if we are at i=6 and our value is

    // %11010100 it would the code compares it to %01000000

    // and proceeds to set pinState to 1.

    if ( myDataOut & (1<<i) ) {

      pinState= 1;

    }

    else { 

      pinState= 0;

    }

 

    //Sets the pin to HIGH or LOW depending on pinState

    digitalWrite(myDataPin, pinState);

    //register shifts bits on upstroke of clock pin 

    digitalWrite(myClockPin, 1);

    //zero the data pin after shift to prevent bleed through

    digitalWrite(myDataPin, 0);

  }

 

  //stop shifting

  digitalWrite(myClockPin, 0);

}

 

Numerous shift registers can be linked in this was to give the ATTiny the ability to control numerous outputs whilst using only three pins.


Line Decoder SN74HCT138N

The 74HCT138 is a decoder/demultiplexer (DEMUX) inverting. That means that it can turn 3 digital outputs into 8 digital outputs. Inverting means that the encoded output will actually be LOW, not HIGH as would be expected. The 74HC138 / 74HCT138 decoders accept three binary weighted address inputs (A0, A1, A2) and when enabled, provide 8 mutually exclusive active LOW outputs (Y0 to Y7).

 

 

Truth table

 

Connect the 74HC138N to the ATTiny as follows:

 

74HC138N                         ATTiny

A0                                      PB1

A1                                      PB2

A2                                      PB3

E3                                       PB4

E1                                       GND

E2                                       GND

VCC                                   5V

GND                                   GND

Y0-Y4                                LED1 - 5                                          

 

E1 and E2 are LOW (GND), therefore, E3 (connected to ATTiny pin PB4) is HIGH.

 

Upload the following to the ATTiny using the programmer. The program will cycle through the 5 LEDs.that are connected to the line decoder.

 

const int selA0 = PB1;

const int selA1 = PB2;

const int selA2 = PB3;

const int E3 = PB4;

 

void setup()

{

 

// initialize the control outputs

pinMode(selA0, OUTPUT);

pinMode(selA1, OUTPUT);

pinMode(selA2, OUTPUT);

pinMode(E3, OUTPUT);

 

 

digitalWrite(selA0, LOW);

digitalWrite(selA1, LOW);

digitalWrite(selA2, LOW);

digitalWrite(E3, HIGH);

 

}

 

void loop()

{

/*turn on LED 1 */

digitalWrite(selA0, LOW);

digitalWrite(selA1, LOW);

digitalWrite(selA2, LOW);

delay(1000);

 

/*turn on LED 2 */

digitalWrite(selA0, HIGH);

digitalWrite(selA1, LOW);

digitalWrite(selA2, LOW);

delay(1000);

 

/*turn on LED 3 */

digitalWrite(selA0, LOW);

digitalWrite(selA1, HIGH);

digitalWrite(selA2, LOW);

delay(1000);

 

/*turn on LED 4 */

digitalWrite(selA0, HIGH);

digitalWrite(selA1, HIGH);

digitalWrite(selA2, LOW);

delay(1000);

 

/*turn on LED 5 */

digitalWrite(selA0, LOW);

digitalWrite(selA1, LOW);

digitalWrite(selA2, HIGH);

delay(1000);

 

}

 


The core that is used from here onwards was devised and developed by James Sleeman. Initially, I began experimenting with it just for serial communication on the ATTiny but it can be used extensively for numerous applicaions. The diagram below shows the pins that can be used for various functions and these will be referenced in the examples that follow.

 

 

Important:

pinMode() must only be used with the "digital pin numbers" 0 .. n

pins default to INPUT, you do not need to pinMode() to INPUT if you are only ever doing an analogRead() from the pin.

analogRead() must only be used with the "analog pin numbers" A0 .. n

 

The Baud Rate is IGNORED on the Tiny13 due to using a simplified serial. The actual Baud Rate used is dependant on the processor speed.

 

9.6MHz will be 57600 Baud

4.8MHz will be 9600 Baud

1.2MHz will be 9600 Baud

 

The default settings in the Arduino IDE should be set to the following:

 

  Tools > Board                                : ATTiny13

  Tools > Processor Version            : ATTiny13

  Tools > Use Bootloader                  : No (ISP Programmer Upload)

  Tools > Processor Speed                 : 9.6MHz Internal Oscillator

  Tools > Millis, Tone Suppor         : Millis Available, No Tone

  Tools > Millis Accuracy                 : 1.666%

  Tools > Print Support                    : Bin, Hex, Dec Supported

  Tools > Serial Support                  : Half Duplex, Read+Write

 

1.  Copy this URL

https://raw.githubusercontent.com/sleemanj/optiboot/master/dists/package_gogo_diy_attiny_index.json

2. Open the Arduino IDE and chooe File > Preferences locate the "Additional Boards Manager URLs" at the bottom of the window

3. Click the window icon next to that field to edit it

4. Paste the URL from 1 into this field on a new line and click OK, and OK to close the preferences

5. Go to Tools > Board > Boards Manager

6. Wait for the update download to finish

7. In "Filter your search" type Tiny13 and choose to install the "DIY ATtiny by James Sleeman"

8. Close the boards manager

9. Choose Tools > Board > DIY ATtiny > ATtiny13

10. Choose Tools > Burn Bootloader to set the fuses correctly if you are not certain they are correct

 

 

 

 

 


Serial Communication

Serial communication on the ATTiny13A is quite straight forward once the IDE and board are set up correctly. To ensure that the board is set correctly, the following steps should be taken with the ATTiny13A board connected to the Arduino ISP as described earlier: Note that all examples following this topic use this set up (core).

 

To test that the board is set up correctly (see previously) and to demonstrate serial output,  choose File > Examples > ATTinyCore > Tiny13 > Communication > ASCII Table. Upload sketch using the Arduino ISP programmer.

 

Disconnect programmer and then connect the “serial adapter” i.e. pin 5 of the ATTiny connects to TX (pin 1) of the Arduino, and pin 6  of the ATTiny connects to RX (pin 0) of the Arduino

Open the Serial Monitor and select 57600 baud rate. The program will print a table of ASCII characters to the Serial Monitor

 

 

A very useful and important part of this program is the confirmation that the usual parameters for printing to the Serial Monitor can be used (to a certain extent). Below is a very basic program which initializes the baud rate,  prints “Hello”, waits for a second (1000 milliseconds) and then repeats indefinitely.

 

void setup() {

  // put your setup code here, to run once:

Serial.begin(57600);

}

void loop() {

  // put your main code here, to run repeatedly:

  Serial.println("Hello");

  delay(1000);

}

 

Now we have the ability to print to the Sereial Monitor, we can incorporate this feature into numerous applications and projects.


Serial Menu

The following example prints a menu to the Serial Monitor. There are four menu options to choose from. The user can select an option by sending a single character that the program reads. Depending on the option chosen, the program will write a response to the Serial Monitor.

 

In the Arduino IDE, select File > Examples > ATTinyCore > Tiny13 > Communication > MenuDemo. Upload sketch using the Arduino ISP programmer.

 

void setup()

{

  Serial.begin(57600); // Set the baud rate

}

 

void loop()

{

 

  Serial.println(F("\n~~ Tiny Menu ~~\n")); 

  Serial.println(F("1. Say Hello"));

  Serial.println(F("2. Say Goodbye"));

  Serial.println(F("3. Sing"));

  Serial.println(F("4. Jack"));

 

  switch(Serial.read_char_blocking())

  {

    case '1':

      Serial.println(F(">> Hello"));

      break;

    case '2':

      Serial.println(F(">> Goodbye"));

      break;

    case '3':

      Serial.println(F(">> Daisy, daisy, give me your answer do."));

      break;

    case '4':

      for(uint8_t x = 0; x < 100; x++)

      {

        Serial.println(F("All work and no play makes Jack a dull boy."));      

      }

      break;

    default:

      Serial.println(F("* Unkown Command *"));

      break;

  }

  delay(1000);

}

 

Disconnect programmer and then connect the “serial adapter” i.e. pin 5 of the ATTiny connects to TX (pin 1) of the Arduino, and pin 6  of the ATTiny connects to RX (pin 0) of the Arduino

Open the Serial Monitor and select 57600 baud rate if not already selected.

 

 

By sending an option (1,2,3 or 4), the ATTiny will respond according to the selection. This example demonstrates how two way communication with the ATTiny can be implemented.

 

 


Read Serial ASCII String

The following example reads a string from Serial Port and prints a string to the Serial Monitor. The program asks your name and then says hello. With regard to reading strings over  Serial on the Tiny13, there is something important to note. Because of a lack of hardware serial support, interrupts are disabled for the entire read of the string.  That means that

 millis() will "lose time" for the period you are reading the string.

 

In the Arduino IDE, select File > Examples > ATTinyCore > Tiny13 > Communication > ReadASCIIString. Upload sketch using the Arduino ISP programmer.

 

void setup()

{

  Serial.begin(57600); // Set the baud rate             }

 

void loop()

{   

  Serial.println(F("What is your name traveller?")); 

  char buf[10];

  do

  {   

    Serial.read_str(buf, sizeof(buf));  

  } while(!buf[0]);

 

  Serial.print(F("Nice to meet you "));

  Serial.println(buf);

}

 

Disconnect programmer and then connect the “serial adapter” i.e. pin 5 of the ATTiny connects to TX (pin 1) of the Arduino, and pin 6  of the ATTiny connects to RX (pin 0) of the Arduino

Open the Serial Monitor and select 57600 baud rate if not already selected.

 

 

You will be promted to input your name. Once you have done this, the program will serially print “Nice to meet you (your name)”.
Serial Digital Clock

 

choose File > Examples > ATTinyCore > Tiny13 > Communication > SerialDigitalClock. Upload sketch using the Arduino ISP programmer.

 

uint8_t  hours = 0, mins = 0, secs = 0;   

uint32_t lastMillis = 0;

 

void setup()

{

  // If you have a calibration number (OSCCAL) for your chip enter it here

  // and uncomment.  The OSCCAL is specific to the chip you are looking at

  // right now, not the type of chip, the actual physical chip you have in

  // your hand, at the specific temperature in your vicinity right now,

  // whatever that is.  If you have not calibrated it, then the chip will

  // have a default calibration value built into it at the Atmel factor.

  // OSCCAL=84;

 

  Serial.begin(57600); // NOTICE the baud rate specified is ignored on the T13

                       //  Instead it is hard coded as follows...

                       //  Processors at 9.6MHz ==> 57600

                       //  Processors at 4.8 and 1.2MHz ==> 9600         

}

 

void loop()

{ 

  if(millis()-lastMillis >= REAL_MILLIS(1000))

  {

       lastMillis += REAL_MILLIS(1000);

    secs++;

    if(secs == 60)

    {

      secs = 0;

      mins++;

    }

   

    if(mins == 60)

    {

      mins = 0;

      hours++;

    }

   

    if(hours == 24)

    {

      hours = 0;

    }

 

    Serial.print( hours );

    Serial.print(':');

    Serial.print( mins );

    Serial.print(':');

    Serial.println(secs);       

  }

   

} 

 

Using the techniques above, you could expect to gain or lose 5 to 10 minutes a day. If you have not calibrated the ATTiny oscillator then the error will potentially be quite a lot more.. This can be done by using the OSCCAL program in the Examples folder.

 

Note that even though the example is a "clock" we don't need totally accurate millis because we are using REAL_MILLIS(). 

As long as millis() ticks along at a constant rate, REAL_MILLIS() provides an adjustment to be more accurate.

However there is still interaction between REAL_MILLIS() and millis' accuracy.

 

Disconnect programmer and then connect the “serial adapter” i.e. pin 5 of the ATTiny connects to TX (pin 1) of the Arduino, and pin 6  of the ATTiny connects to RX (pin 0) of the Arduino

Open the Serial Monitor and select 57600 baud rate. The program will a running digital clock to the Serial Monitor.

 

 

 

 


Random Number Generator

This program will generate random numbers and print them to the Serial Monitor.  The ATTiny13A is too small to use the stdlb random number generator, so here is a simplistic 16bit XOR random number generator. The random numbers are not particularly great in a statistical sense, but the program does produce some randomness.

 

The tiny_random() function will return numbers from 0 to 65534 inclusive. The implementation is from adapted frpm here:

 

http://www.arklyffe.com/main/2010/08/29/xorshift-pseudorandom-number-generator/

 

 (modified to subtract 1 from the result to get it rooted to zero).  It's implemented in the WMath.cpp in this core.

 

Upload the following sketch via the Arduino ISP programmer (the program is available in the Examples folder).

 

void setup()

{

  Serial.begin(57600);

                      

  // Seed the generator

  tiny_srandom(analogRead(A3)); 

}

 

void loop()

{

  Serial.println(tiny_random());

  delay(1000);

}

 

Disconnect the ISP programmer and connect the serial adapter and open the Serial Monitor.

 


Physical Pixel

This is an example of using the ATTiny to receive data from the computer. The ATTiny turns on an LED when it receives the character 'H', and turns off the LED when it receives the character 'L'. The data is sent from the Arduino Serial Monitor.

 

Upload the following sketch via the Arduino ISP programmer.

 

const int ledPin = PB4; // physical pin 3

//int incomingByte;      // a variable to read incoming serial data into

 

void setup() {

  Serial.begin(57600);

  pinMode(ledPin, OUTPUT);

}

 

void loop() {

Serial.println ("Choose L or H"); 

  char buf[10];

  do

  {   

    Serial.read_str(buf, sizeof(buf));  

  } while(!buf[0]);

 

if ((buf) == 'H') {

      digitalWrite(ledPin, HIGH);

    }

    // if it's an L (ASCII 76) turn off the LED:

    if ((buf) == 'L') {

      digitalWrite(ledPin, LOW);

    }

 delay(2000);

 // Serial.println(buf);

}

 

Disconnect the ISP programmer and connect the serial adapter and connect an LED to pin 3 (PB4) of te ATTiny (longest leg of LED to this pin, shortest leg of LED to GND (pin 4). Open the Serial Monitor.

 

When you send “H” via the Serial Monitor, the LED will turn on. Conversley, when you send “L” via the Serial Monitor, the LED will turn off.

 

 


Randomly flashing LED with PRNG

Here an LED is made to randomly flash using BBS (Blum-Blum-Shumb) algorithm as PRNG (Pseudo Random Number Generator) to generate 16-bit (pseudo) random numbers. The less significant bit of randomly generated number is a major factor in decision to turn the the LED on/off.

 

Attach an LED via a 220 ohm resistor to pin 5 (PB0) of the ATTiny. Connect the other leg (shorter leg) of the LED to GND. Upload the following sketch using the Arduino ISP programmer.

 

#include <avr/io.h>

#include <util/delay.h>

 

#define  LED_PIN  PB0

#define BBS_P    (13)

#define BBS_Q    (97)

#define BBS_SEED (123)

#define DELAY    (64)

 

static uint16_t m;

static uint16_t x;

static uint16_t r;

 

/* Initialize vector of BBS algorithm, where:

-> p: prime number

-> q: prime number

-> seed: random integer greater then 1,

         which is co-prime to 'm',

         where 'm = p*q' and 'GCD(m, seed) == 1'

Note that value of 'm' must be less than '(2^16) - 1'

*/

static void

bbs_init(uint16_t p, uint16_t q, uint16_t seed)

{

 

  m = p * q;

  r = x = seed;

}

 

static uint16_t

bbs_next(void)

{

 

  return (r = (r * x) % m);

}

 

int

main(void)

{

 

  /* setup */

  DDRB |= _BV(LED_PIN); // set LED pin as OUTPUT

  bbs_init(BBS_P, BBS_Q, BBS_SEED); // initialize BBS alg.

 

  /* loop */

  while (1) {

    if (bbs_next() & 1) {

      PORTB |= _BV(LED_PIN);

    } else {

      PORTB &= ~_BV(LED_PIN);

    }

    _delay_ms(DELAY);

  }

}
Temperature Sensor

 

Here, we are going to use an LM35 precision analog temperature sensor. It has 3-pins; 5V, GND and temperature.

 

As you look at the flat face of the sensor with the pins hanging downwards, the left pin is the 5V pin and should be attached to the 5V pin (pin 8) of the ATTiny. The right pin of the sensor is ground and should be connected to the ATTiny GND pin (pin 4). Finally, the central pin should be connected directly to pin 3 (PB4) of the ATTiny. Notice that we are not using a breadboard here. This is because if we were to use a breadboard, the temperature wouldn’t be very stable. If you must use a breadboard, you would be well advised to add some sort of filter.

 

Upload the following sketch via the Arduino ISP programmer. Disconnect the ISP programmer and connect the serial adapter and open the Serial Monitor. You should see the temperature reading value being updated every two seconds. If you grab hold of the sensor or breathe on it, you should see the temperature rise. Try altering the delay so that you see the temperature being updated at different intervals (remember that this is milliseconds so delay(2000); pauses for two seconds).

 

const uint8_t INPUT_PIN = A2; //pin 3

 

void setup()

{

  Serial.begin(57600);        

 

}

void loop()

{ 

  uint16_t sensorValue = analogRead(INPUT_PIN);

 

  Serial.println (sensorValue)*1000/1024*5000;

 

  delay (2000);       

}

 

When the ATTiny is using the 5V reference with 10bit analog to digital conversion (ADC) it has a 1024 count. Therefore, we have to perform the following calculation on the sensor measurement to give true temperature in Centigrade.

 

Temprature = (sensorValue)*1000/1024*5000, i.e. temp = Vin * 1000 / 1024 * Vref [milivolts]

 

The serial output can be enhanced by inserting the word “Temperature” before and the words “degrees centigrade” after the temperature.The temperature sensorcan easily be incorporated into larger projects such as a weather station project.


TM1637 Seven Segment Display

Modules based on TM1637 provide two signal connections (CLK and DIO) and two power connections (VCC and GND). Signal pins can be connected to any pair of digital pins of the AVR chip. Signal pins configuration is defined at the top of library header file, where it can be modifed.

 

The example below will enable the ATTiny to read the temperature from a LM35 sensor (see earlier) and display it on the TM1635 module.

 

Connect the LM35 data pin to PB4 (pin 3) of the ATTiny. Connect GND to GND and VCC to 5V. Connect the CLK pin of the TM1637 to PB1 (pin 6) of the ATTiny and the DIO pin of the TM1647 to PB0 (pin 5) of the ATiny. Connect GND and VCC of the TM1637 to GND and VCC, respectively.

 

Upload the following sketch via the Arduino ISP programmer.  Though the sketch is quite long, it has been included in its entireity so that the reader can see the construction and the necessary level of programming required. This can be much reduced by using a library.

 

#include <stdint.h>

#include <avr/io.h>

#include <avr/pgmspace.h>

#include <util/delay.h>

 

#define  LM35_DATA_PIN PB4

 

#define TM1637_DIO_HIGH()   (PORTB |= _BV(TM1637_DIO_PIN))

#define TM1637_DIO_LOW()    (PORTB &= ~_BV(TM1637_DIO_PIN))

#define TM1637_DIO_OUTPUT()   (DDRB |= _BV(TM1637_DIO_PIN))

#define TM1637_DIO_INPUT()    (DDRB &= ~_BV(TM1637_DIO_PIN))

#define TM1637_DIO_READ()     (((PINB & _BV(TM1637_DIO_PIN)) > 0) ? 1 : 0)

#define TM1637_CLK_HIGH()   (PORTB |= _BV(TM1637_CLK_PIN))

#define TM1637_CLK_LOW()    (PORTB &= ~_BV(TM1637_CLK_PIN))

 

// Main Settings

#define TM1637_DIO_PIN      PB0

#define TM1637_CLK_PIN      PB1

#define TM1637_DELAY_US     (5)

#define TM1637_BRIGHTNESS_MAX   (7)

#define TM1637_POSITION_MAX   (4)

 

// TM1637 commands

#define TM1637_CMD_SET_DATA   0x40

#define TM1637_CMD_SET_ADDR   0xC0

#define TM1637_CMD_SET_DSIPLAY    0x80

 

// TM1637 data settings (use bitwise OR to contruct complete command)

#define TM1637_SET_DATA_WRITE   0x00 // write data to the display register

#define TM1637_SET_DATA_READ    0x02 // read the key scan data

#define TM1637_SET_DATA_A_ADDR    0x00 // automatic address increment

#define TM1637_SET_DATA_F_ADDR    0x04 // fixed address

#define TM1637_SET_DATA_M_NORM    0x00 // normal mode

#define TM1637_SET_DATA_M_TEST    0x10 // test mode

 

// TM1637 display control command set (use bitwise OR to consruct complete command)

#define TM1637_SET_DISPLAY_OFF    0x00 // off

#define TM1637_SET_DISPLAY_ON   0x08 // on

 

static void TM1637_send_config(const uint8_t enable, const uint8_t brightness);

static void TM1637_send_command(const uint8_t value);

static void TM1637_start(void);

static void TM1637_stop(void);

static uint8_t TM1637_write_byte(uint8_t value);

 

static uint8_t _config = TM1637_SET_DISPLAY_ON | TM1637_BRIGHTNESS_MAX;

static uint8_t _segments = 0xff;

 

static void LM35_init(void);

static int LM35_read(void);

static int analog_read(uint8_t pin);

 

 

/**

 * Initialize TM1637 display driver.

 * Clock pin (TM1637_CLK_PIN) and data pin (TM1637_DIO_PIN)

 * are defined at the top of this file.

 */

void TM1637_init(const uint8_t enable, const uint8_t brightness);

 

/**

 * Turn display on/off.

 * value: 1 - on, 0 - off

 */

void TM1637_enable(const uint8_t value);

 

/**

 * Set display brightness.

 * Min value: 0

 * Max value: 7

 */

void TM1637_set_brightness(const uint8_t value);

 

/**

 * Display raw segments at position (0x00..0x03)

 *

 *      bits:

 *        -- 0 --

 *       |       |

 *       5       1

 *       |       |

 *        -- 6 --

 *       |       |

 *       4       2

 *       |       |

 *        -- 3 --

 *

 * Example segment configurations:

 * - for character 'H', segments=0b01110110

 * - for character '-', segments=0b01000000

 * - etc.

 */

void TM1637_display_segments(const uint8_t position, const uint8_t segments);

 

/**

 * Display digit ('0'..'9') at position (0x00..0x03)

 */

void TM1637_display_digit(const uint8_t position, const uint8_t digit);

 

/**

 * Display colon on/off.

 * value: 1 - on, 0 - off

 */

void TM1637_display_colon(const uint8_t value);

 

/**

 * Clear all segments (including colon).

 */

void TM1637_clear(void);

 

 

PROGMEM const uint8_t _digit2segments[] =

{

  0x3F, // 0

  0x06, // 1

  0x5B, // 2

  0x4F, // 3

  0x66, // 4

  0x6D, // 5

  0x7D, // 6

  0x07, // 7

  0x7F, // 8

  0x6F  // 9

};

 

 

int main(void)

{

  int temp;

        uint8_t firstdig;

        uint8_t seconddig;

        uint8_t thirddig;

 

  /* setup */

  TM1637_init(1/*enable*/, 5/*brightness*/);

 

  /* setup */

  LM35_init();

 

  /* loop */

  while (1) {

 

        // read ADC value 16 times and compute mean for accuracy

       temp = 0;

       for(uint8_t counts = 0; counts < 16; counts++)  temp = temp + LM35_read();

       temp = temp >> 4;

 

       // wyswietlenie znaku stopni NA OSTATNIEJ POZYCJI

       TM1637_display_segments(3, 99);

 

       //przeliczenie cyfr na wszystkich pozycjach

                firstdig = temp / 100;

                seconddig = (temp - (firstdig * 100))/ 10;

                thirddig =  temp - (firstdig * 100) - (seconddig*10);

 

        // wyswietlamy od pozycji 1giej na wyswietlaczu

        // ostatnia pozycja to znak minus lub stopnie

                TM1637_display_digit(0, firstdig);

                TM1637_display_digit(1, seconddig);

                TM1637_display_digit(2, thirddig);

    //  pomiar co pol sekundy

                _delay_ms(500);

  }

  /* loop */

 

}

 

void

LM35_init(void)

{

 

  DDRB &= ~_BV(LM35_DATA_PIN); // set data pin as INPUT

}

 

int

LM35_read(void)

{

  int temp;

 

  temp = analog_read(LM35_DATA_PIN); // read analog value from sensor

  temp = ((((uint32_t)temp * 1000UL) >> 10) * 5); // convert value using euqation temp = Vin * 1000 / 1024 * Vref [milivolts]

 

  return temp;

}

 

int

analog_read(uint8_t pin)

{

  uint8_t low, high;

 

  switch(pin) {

  case PB2: ADMUX = _BV(MUX0); break; // ADC1

        case PB4: ADMUX = _BV(MUX1); break; // ADC2

        case PB3: ADMUX = _BV(MUX0)|_BV(MUX1); break; // ADC3

        case PB5: // ADC0

  default: ADMUX = 0; break;

  }

 

  ADMUX &= ~_BV(REFS0); // explicit set VCC as reference voltage (5V)

  ADCSRA |= _BV(ADEN);  // Enable ADC

  ADCSRA |= _BV(ADSC);  // Run single conversion

  while(bit_is_set(ADCSRA, ADSC)); // Wait conversion is done

 

  // Read values

  low = ADCL;

        high = ADCH;

 

        // combine two bytes

        return (high << 8) | low;

}

 

 

void

TM1637_init(const uint8_t enable, const uint8_t brightness)

{

 

  DDRB |= (_BV(TM1637_DIO_PIN)|_BV(TM1637_CLK_PIN));

  PORTB &= ~(_BV(TM1637_DIO_PIN)|_BV(TM1637_CLK_PIN));

  TM1637_send_config(enable, brightness);

}

 

void

TM1637_enable(const uint8_t value)

{

 

  TM1637_send_config(value, _config & TM1637_BRIGHTNESS_MAX);

}

 

void

TM1637_set_brightness(const uint8_t value)

{

 

  TM1637_send_config(_config & TM1637_SET_DISPLAY_ON,

    value & TM1637_BRIGHTNESS_MAX);

}

 

void

TM1637_display_segments(const uint8_t position, const uint8_t segments)

{

 

  TM1637_send_command(TM1637_CMD_SET_DATA | TM1637_SET_DATA_F_ADDR);

  TM1637_start();

  TM1637_write_byte(TM1637_CMD_SET_ADDR | (position & (TM1637_POSITION_MAX - 1)));

  TM1637_write_byte(segments);

  TM1637_stop();

}

 

void

TM1637_display_digit(const uint8_t position, const uint8_t digit)

{

  uint8_t segments = (digit < 10 ? pgm_read_byte_near((uint8_t *)&_digit2segments + digit) : 0x00);

 

  if (position == 0x01) {

    segments = segments | (_segments & 0x80);

    _segments = segments;

  }

 

  TM1637_display_segments(position, segments);

}

 

void

TM1637_display_colon(const uint8_t value)

{

  if (value) {

    _segments |= 0x80;

  } else {

    _segments &= ~0x80;

  }

  TM1637_display_segments(0x01, _segments);

}

 

void

TM1637_clear(void)

{

  uint8_t i;

 

  for (i = 0; i < TM1637_POSITION_MAX; ++i) {

    TM1637_display_segments(i, 0x00);

  }

}

 

void

TM1637_send_config(const uint8_t enable, const uint8_t brightness)

{

 

  _config = (enable ? TM1637_SET_DISPLAY_ON : TM1637_SET_DISPLAY_OFF) |

    (brightness > TM1637_BRIGHTNESS_MAX ? TM1637_BRIGHTNESS_MAX : brightness);

 

  TM1637_send_command(TM1637_CMD_SET_DSIPLAY | _config);

}

 

void

TM1637_send_command(const uint8_t value)

{

 

  TM1637_start();

  TM1637_write_byte(value);

  TM1637_stop();

}

 

void

TM1637_start(void)

{

 

  TM1637_DIO_HIGH();

  TM1637_CLK_HIGH();

  _delay_us(TM1637_DELAY_US);

  TM1637_DIO_LOW();

}

 

void

TM1637_stop(void)

{

 

  TM1637_CLK_LOW();

  _delay_us(TM1637_DELAY_US);

 

  TM1637_DIO_LOW();

  _delay_us(TM1637_DELAY_US);

 

  TM1637_CLK_HIGH();

  _delay_us(TM1637_DELAY_US);

 

  TM1637_DIO_HIGH();

}

 

uint8_t

TM1637_write_byte(uint8_t value)

{

  uint8_t i, ack;

 

  for (i = 0; i < 8; ++i, value >>= 1) {

    TM1637_CLK_LOW();

    _delay_us(TM1637_DELAY_US);

 

    if (value & 0x01) {

      TM1637_DIO_HIGH();

    } else {

      TM1637_DIO_LOW();

    }

 

    TM1637_CLK_HIGH();

    _delay_us(TM1637_DELAY_US);

  }

 

  TM1637_CLK_LOW();

  TM1637_DIO_INPUT();

  TM1637_DIO_HIGH();

  _delay_us(TM1637_DELAY_US);

 

  ack = TM1637_DIO_READ();

  if (ack) {

    TM1637_DIO_OUTPUT();

    TM1637_DIO_LOW();

  }

  _delay_us(TM1637_DELAY_US);

 

  TM1637_CLK_HIGH();

  _delay_us(TM1637_DELAY_US);

 

  TM1637_CLK_LOW();

  _delay_us(TM1637_DELAY_US);

 

  TM1637_DIO_OUTPUT();

 

  return ack;

}

 

 

The temperature from a LM35 sensor will be displayed on the TM1635 module.


TM1637 Seven Segment Display With Library.

A dedicated TM1637 Seven Segment Display library has been written specifically for the ATTiny13. This enables the user to be more flexible with the programming of the microcontroller and simplifies the whole process.

 

Upload the following program using the Arduino ISP programmer then disconnect the programmer.

 

#include <stdint.h>

#include <avr/io.h>

#include <util/delay.h>

#include "tm1637.h"

#include "tm1637.c"

 

int

main(void)

{

  uint8_t n, k = 0;

 

  /* setup */

  TM1637_init(1/*enable*/, 5/*brightness*/);

 

  /* loop */

  while (1) {

    for (n = 0; n < TM1637_POSITION_MAX; ++n) {

      TM1637_display_digit(n, (k + n) % 0x10);

    }

    TM1637_display_colon(1);

    _delay_ms(200);

    TM1637_display_colon(0);

    _delay_ms(200);

    k++;

  }

}

 

Connect the CLK pin of the TM1637 to PB1 (pin 6) of the ATTiny and the DIO pin of the TM1647 to PB0 (pin 5) of the ATiny. Connect GND and VCC of the TM1637 to GND and VCC, respectively.

 

You will see the numbers “0123456789” counting up and scrollimg displayed on the TM1637 module.

 

 


DHT-11 Temperature and Humidity Sensor

A very poular sensor that is widely used is the DHT11 humidity sensor. This is a digital humidity and temperature sensor and has four pins. The measurement resolution of this module is 1°C or 1% relative humidity. Here, it will just be used for measuring relative humidity; measurement of  temperature is better done with the more accurate and sensitive LM35 (see previous).

 

Simply connect Data pin to ATTiny pin 3 (PB4) and pins to +5V and GND to VCC and GND, respectively

 

Upload the following program using the Arduino ISP programmer then disconnect the programmer.

 

/**

 * Copyright (c) 2019, Łukasz Marcin Podkalicki <lpodkalicki@gmail.com>

 * ATtiny13/030

 * Read data from DHT11 sensor and log temperature and humidity

 * using software uart (19200/8N1).

 *

 * Settings:

 *  FUSE_L=0x6A

 *  FUSE_H=0xFF

 *  F_CPU=1200000

 */

 

#include <avr/io.h>

#include <util/delay.h>

 

 

//#define DHT_PIN            PB0 //physical pin 5

#define DHT_PIN            PB4 //physical pin 3

 

#define DHT_ERR_OK         (0)

#define DHT_ERR_TIMEOUT    (-1)

 

#define DHT_PIN_INPUT()    (DDRB &= ~_BV(DHT_PIN))

#define DHT_PIN_OUTPUT()   (DDRB |= _BV(DHT_PIN))

#define DHT_PIN_LOW()      (PORTB &= ~_BV(DHT_PIN))

#define DHT_PIN_HIGH()     (PORTB |= _BV(DHT_PIN))

#define DHT_PIN_READ()     (PINB & _BV(DHT_PIN))

#define DHT_TIMEOUT        (10)

 

static void dht_init(void);

int8_t dht_read(uint8_t *temperature, uint8_t *humidity);

//Serial.begin (19200);

int

main(void)

{

    uint8_t temperature, humidity;

 

    /* setup */

    dht_init();

 

    /* loop */

    while (1) {

        dht_read(&temperature, &humidity);

        Serial.print ("T:");

        Serial.print (temperature);

        Serial.print (" C, H:");

        Serial.print (humidity);

        Serial.print ("%\n");

        Serial.println ("");

        _delay_ms(1000);

    }

}

 

void

dht_init(void)

{

 

    DHT_PIN_INPUT();

    DHT_PIN_HIGH();

}

 

static int8_t

dht_await_state(uint8_t state)

{

    uint8_t counter = 0;

    while ((!DHT_PIN_READ() == state) && (++counter < DHT_TIMEOUT)) { _delay_us(1); };

    return counter;

}

 

int8_t

dht_read(uint8_t *temperature, uint8_t *humidity)

{

    uint8_t i, j, data[5] = {0, 0, 0, 0, 0};

 

    /* send start sequence */

    DHT_PIN_OUTPUT();

    DHT_PIN_LOW();

    _delay_ms(20);

    DHT_PIN_INPUT();

    DHT_PIN_HIGH();

 

    /* read response sequence */

    if (dht_await_state(0) < 0 || dht_await_state(1) < 0 || dht_await_state(0) < 0) {

        return DHT_ERR_TIMEOUT;

    }

 

    /* read data */

    for (i = 0; i < 5; ++i) {

        for (j = 0; j < 8; ++j) {

            data[i] <<= 1;

            data[i] |= !!(dht_await_state(1) > 0 && dht_await_state(0) > 1);

        }

    }

 

    *temperature = data[2];

    *humidity = data[0];

 

    return DHT_ERR_OK;

}

 

 

Disconnect the ISP programmer and connect the serial adapter. Open The Serial Monitor at 57600 baud rate.

You will see that the humidity measurement displayed and continually updated.

 

If you breathe on the sensor, you should see the humidity measurement change. Try altering the delay interval or the way that the data is displayed in the Serial Monitor. This sensor can be used in conjunction with other sensors/modules as part of larger projects, for example a weather monitoring station.

 

 

 


Light Sensor

Light sensors, also known as photo resistors or light dependant resistors (LDR) are generally quite basic and un-calibrated. In this example, I have used a GL5537 LDR but there are plenty of others that perform equally as well. The LDR changes its resistance depending on the amount of light and we can measure this change using one of the ATTiny analog pins.

 

The LDR has only two pins so connect one of these pins to GND (ground) and the other pin to a 10k ohm pull up resistor and to the ATtiny analog pin 3 (A2)  (see Arduino Section for wiring diagram which can be adapted for the ATTiny). Upload the following program using the Arduino ISP programmer then disconnect the programmer. Connect the serial adapter and open the Serial Monitor.

 

const uint8_t INPUT_PIN = A2; //pin 3

void setup()

{

  Serial.begin(57600);         // NOTICE the baud rate specified is ignored on the T13

                               //  Instead it is hard coded as follows...

                               //  Processors at 9.6MHz ==> 57600

                              //  Processors at 4.8 and 1.2MHz ==> 9600 

}

void loop()

{ 

  uint16_t sensorValue = analogRead(INPUT_PIN);

  //Serial.println(sensorValue);

  Serial.println(sensorValue)*1000/1024;

  delay(2000);       

}

 

Placing your hand (or piece of paper) over the sensor results in a change of values displayed. The more light, the lower the reading.

 

 

As the measured resistance varies greatly from bright light to darkness, we need to either use a lookup table or perform calculations on the readings to convert to lux values.

 

Below is a table to reference when changing the ADC reading to lux

 

Vcc        5V                                     

Pullup resistor     10000    ohms

                            

lux

ohms

Voltage

ADC

Scaling

0

 

1023

 

 

1

200000

4.76

975

-0.020937188

10

30000

3.75      

768

-0.043428309

80

5000

1.67

341

-0.1640625

120

4000

1.43

293

-0.8203125

150

3000

1.15

236

-0.533203125

250

2000

0.83

171

-1.5234375

300

1800

0.76

156

-3.45703125

800

700

0,33

67

-5.604580966

 

There is a program in the Arduino Section that can be adopted for the ATTiny.

The first program (without the conversion to lux) would be sufficient if you just want to detect the difference between light and shadow, if a light is on or off or there is just a change in brightness.

 

These inexpensive sensors can be readily bought on the internet. They can be used as part of larger projects such as monitoring light around the home and switching lights on and off depending on levels of light detected.

 


Sound Sensor

A sound sensor can, and is, a very useful item. It can be used to trigger lights, doors, alarms etc or even used to control a smart vehicle.

The sensor detects sound through a microphone and this sound is passed through a LM393 op amp. The particular one used here has an operating voltage of 3.3V-5V and has a signal output indicator LED which comes on when a sound is detected. The output is low when there is sound and high when there is no sound (i.e. LOW and HIGH pin states respectively.

The three pin version of this module connects to the ATTiny as follows:

VCC                     5V

GND                    GND

OUT                     ATTiny pin 2 (PB2)

As the output is digital, we can only detect when there is sound detected or not. If we wanted to detect relative levels of sound, we would need a module that has an analog output.

Connect the module to your ATTiny as above and then. Upload the following program using the Arduino ISP programmer then disconnect the programmer.

 

const uint8_t SOUND_PIN = 2;   //PB2, physical pin 7

 

void setup()

{                      

  Serial.begin(57600);        

}

 

void loop()

{ 

  uint8_t noiseState = digitalRead(SOUND_PIN);

  

  Serial.println(noiseState);

  delay(200);     

}

 

Connect the serial adapter and open the Serial Plotter and make some noise. You will see that the output changes as the sensor detects the sounds. You may need to alter the sensitivity by adjusting the onboard potentiometer.

By making the delay shorter, the system will become more responsive.

 


Flame Detection Sensor

The 4 pin flame detection sensor is generally an infrared (IR) receiver which can detect IR radiation between 760 nm and 1100 nm.

To test the module, a flame should be set of approximately 80cm from the sensor. If using a flame larger than that given by a lighter, this will be detected at a greater distance.

The module has a detection angle of 60 degrees and sensitivity is adjustable using the on-board digital potentiometer. It has an operating voltage of 3.3V to 5V and outputs of both digital and analog. Here is the pinout of the module:

VCC:     VCC

GND:     GND.

DO:        TTL switch signal output.

AO:        Analog Output.

 

Connect the analog pin of the module to the ATtiny analog pin A2 (physical pin 3 of the ATTiny, see core diagram) as well as GND to GND and VCC to VCC. Upload the following program using the Arduino ISP programmer then disconnect the programmer

 

const uint8_t INPUT_PIN = A2;        //physical pin 3

 

void setup() {

 Serial.begin(57600);      

 }

void loop() {

uint16_t sensorValue = analogRead(INPUT_PIN);

  Serial.print("Flame Reading ");    

  Serial.print(sensorValue);                // print out the value

  Serial.println (" ");

 

  delay(1000);              // delay between readings for stability        

}

 

Disconnect the ISP programmer and connect the serial adapter and open the Serial Monitor. Pass a flame in front of the detector and you will see the output to the serial monitor change.

 

 

Close the Serial Monitor and open the Serial Plotter. Again,  pass a flame in front of the detector and you will see the output to the serial monitor change.

 

 


Soil Moisture Sensor

This sensor measures the volumetric content of water in the soil and gives the moisture level as output. The sensor is equipped with both analog and digital output, so it can be used in both analog and digital mode.

 

Connect the analog pin of the module to the ATtiny analog pin 3 (A2) .

 

Upload the following program using the Arduino ISP programmer then disconnect the programmer

 

const uint8_t INPUT_PIN = A2;        //pin 3 of the ATTiny

 

void setup() {

 Serial.begin(57600);      

 }

 

void loop() {

 

int16_t sensorValue = analogRead(INPUT_PIN);

int sensorValue = analogRead(INPUT_PIN)/10;    // read the input on  analog pin A2 and divide the value by 10

 

  Serial.print("Moisture Reading ");    

  Serial.print(sensorValue);                // print out the value

  Serial.println (" ");

 

  delay(2000);              // delay between readings for stability        

}

 

Connect the serial adapter and open the Serial Monitor.

 

 

Though the accuracy of these sensors is questionable, they can still be used in various projects that require soil moisture level data.  An advanced project maybe to monitor the moisture level in a plant pot and if the level falls below a certain level, you could trigger a pump to deliver a certain amount of water. This would be a good way of caring for you houseplants whilst on holiday.


Ultrasound Distance Measurement

 

The HC-SR04 ultrasonic sensor uses sonar to determine distance to an object. It offers excellent non-contact range detection with high accuracy and stable readings. The range is from 2cm to 400 cm (1” to 13 feet).

 

There are four pins on the sensor module and these should be connected as follows:

 

HC SR04              ATTiny

VCC                     5v

GND                    GND

Echo                    pin 3 (physical pin 2)

Trig                    pin 4 (physical pin 3)

 

 

The sketch was compiled from referencing many similar sketches that are available in the public domain. Upload the following program using the Arduino ISP programmer then disconnect the programmer

 

const uint8_t echoPin = 3;                 //(physical pin 2)

const uint8_t trigPin = 4;                   //(physical pin 3)

long duration, distance;  

void setup() {

 Serial.begin (57600);

 pinMode(trigPin, OUTPUT);

 pinMode(echoPin, INPUT);

}

void loop() {

 digitalWrite(trigPin, LOW);

 delayMicroseconds(2);

 digitalWrite(trigPin, HIGH);

 delayMicroseconds(10);

 digitalWrite(trigPin, LOW);

 duration = pulseIn(echoPin, HIGH);

 distance = duration/58;

 Serial.println(distance);

 delay(500);

}

 

Connect the serial adapter and open the Serial Monitor. By moving an object to various distances in front of the detector, the distance displayed changes as in the screen shot below.

 

 

The ATTiny is not very fast and the result of this is that reading are missed (hence the zeros). Changing the pauses (delay) in the program may improve this.

 

Using this core (Core 2), this sketch uses 912 bytes (89%) of program storage space., where the maximum is 1024 bytes. If  the true factor to calculate distance was to put into the program (distance = duration/58; rather than distance = duration/58.;), the program would be too large to upload. In fact, the program would be 1798 bytes (175%) of program storage space before getting rid of this floating point. Ways around this storage problem bur still  correctly (and accurately) calculating the distance, include using one of the following:

 

distance = (duration*10)/582;  This can be done by using int (or long), but no rounding will be done.

 

distance = (((duration*100)/582)+5)/10; This can be done by using int (or long), with an imperfect 1 digit rounding.

 

distance = (((duration*1000)/582)+50)/100; // This can be done by using int (or long), with an imperfect  2 digit rounding.

 

That said, dividing by 58 is totally fine.  This is simply within the margin of error,  the result is still just +/- 1cm difference from the actual distance according to data supplied by James Sleeman:

 

 

The HC SR04 Ultrasonic Sensor can be used in many projects. One that springs to mind would be to use it in a model car or robot as part of a collision avoidance feature.

 


Potentiometer

potentiometer is a simple knob/dial that provides a variable resistance. The result of varying the resistance in a system can then be read by the ATTiny as an analog value. These usually have only three pins; analog in, VCC and GND. The one used in the example below is rated at 10k ohm.

 

The circuit set up for the following example is quite simple. Connect the analog pin (centre pin) of the module to the ATtiny analog pin 3 (A2). Connect one outer pin to GND and the other to VCC.

 

Upload the program using the Arduino ISP programmer then disconnect the programmer

 

const uint8_t INPUT_PIN = A2; //pin 3

 

void setup()

{

  Serial.begin(57600);       

}

 

void loop()

{ 

  uint16_t sensorValue = analogRead(INPUT_PIN);

  //Serial.println(sensorValue);

  Serial.println(sensorValue)*1000/1024;

  delay(2000);       

}

 

Once the sketch is uploaded, disconnect the ISP programmer and connect the serial adapter. Open the Serial Monitor.

 

If you turn the knob on the potentiometer you will see the voltage values change either up or down depending on whether you turn the knob clockwise or anticlockwise.

 

 

Once you are more experienced and building projects that contain several components, I’m sure that you will find the need to use at least one potentiometer.


Data Logging: MakerPlot

MakerPlot is Windows® software for plotting analog and digital data generated by microcontrollers and other devices with ASCII serial outputs.  No proprietary hardware is required – just a serial connection from the microcontroller or other device to the PC. 

With dozens of meters, buttons, switches and text boxes the user has full control of the screen interface design and how information is displayed, plotted, logged to files, printed and more. 

Your microcontroller also has the ability to read information directly from the interfaces for interactive measurement, plotting and control.

Full details and how to purchase, along with how to download a free trail of MakerPlot can be found here (though once tried, you will probably want to purchasing it):

 

http://makerplot.com/home.html

 

After downloading and launching MakerPlot, the user is greeted with a myriad of applications. If they look closer there is a button to access even more on a second page.

 

There is a very comprehensive guide and ten Arduino code samples accessible from the main interface.

 

There are well over a dozen applications available but for the purpose of this work, only a couple of them will be explored. If you download MakerPlot, I’m sure that you will have hours of enjoyment trying out the various applications.

 

Below are a couple of screenshots that show the applications that are available:

 

 

 

 

To test this software, connect an LM35 precision analog temperature sensor as earlier in this section, remembering that the central pin should be connected directly to pin 3 (PB4) of the ATTiny.

 

Upload the following sketch via the Arduino ISP programmer.

 

const uint8_t INPUT_PIN = A2; //pin 3

 

void setup()

{

  Serial.begin(57600);        

}

void loop()

{ 

  uint16_t sensorValue = analogRead(INPUT_PIN);

  Serial.println (sensorValue)*1000/1024*5000;

 

  delay (2000);       

}

 

As mentioned before, when the ATTiny is using the 5V reference with 10bit analog to digital conversion (ADC) it has a 1024 count. Therefore, we have to perform the following calculation on the sensor measurement to give true temperature in Centigrade.

 

Temprature = (sensorValue)*1000/1024*5000, i.e. temp = Vin * 1000 / 1024 * Vref [milivolts]

 

Disconnect the ISP programmer and connect the seial adapter.

Connect your ATTiny to the computer via a USB cable and launch the MakerPlot application. From the first screen, select “Run Standard Interface”.

.

 

 

We will be collecting temperature data every 2 seconds (2000 milliseconds) so we need to alter the axes accordingly. I set the x-axis to 60 seconds and the y-axis to 100. Now select the port and baud rate (56000 for ATTiny). Note the preferred baud rate of 57600 is not available but 56000 works in this example.

 

Select “Log To File” in the bottom panel. MakerPlot is now ready to receive the sensor data.Click the Control Switch to begin data acquisition.

 

 

Open the std_dat.txt file to see the raw data. Here is a screenshot of a portion of my raw data file:

 

 

You can save this file and then import into Excel for some further analysis/plotting.

 

I have only briefly covered a small part of this software package. I’m sure that you will experiment with the other applications within it.

 


NE555 Frequency Adjustable Pulse Generator

This is a square wave pulse generator module based on the ubiquitous NE555 timer IC. The module can be powered from a wide power supply range (4.5 to 12V) and will produce a continuous square wave output between 15Hz to 24KHz which can be set by on on-board multi-turn potentiometer.                                                                         

Connect central pin of the NE555 module to pin 3 (PB4) of the ATTiny, the GND to GND and VCC to VCC.

 

Upload the following sketch via the Arduino ISP programmer

const uint8_t INPUT_PIN = A2; //pin 3

void setup()

{

Serial.begin(57600);

}

void loop()

{

int16_t sensorValue = analogRead(INPUT_PIN);

  Serial.println (sensorValue)*1000/1024*5000;

  delay (200);

}

Disconnect the ISP programmer and connect the seial adapter.

Connect your ATTiny to the computer via a USB cable and open the Serial Monitor.

 

 

To view the data graphically, open the Serial Plotter. The Serial Plotter is limited and the resulting plot is difficut to interpret but you can just about see the pattern of the pulse generated from the module.

 


LM386 Mono Class D Amplifier

The LM386 is a low voltage power amplifier with an inactive power draw of 24mW, which makes it suitable for battery controlled applications.

 

The project runs on ATtiny13 with maximum internal clock source (9.6MHz). This example gives the posibility to use the maximum of hardware PWM frequency (Fast PWM mode).

 

 

The PWM freqency of class D amplifiers should be of course much higher, a hundreds of kHz (some sources says 8 times more than sampling frequency). Unfortunately, in case of ATtiny13 it’s not posible to achieve such parameters. However, for experimentally selected settings of ADC sampling rate (~10kHz) and PWM frequency (37.5kHz) the amplifier sounds very good.

 

I used a cable which had 3.5mm jack plugs on each end. One end goes into my laptop and I cut the other end to reveal three wires, The blue wire connects to pin 2 of the ATTiny (PB3), the red wire to VCC and the black wire to GND. The terminal connectors of the LM386 module connect GND to black and OUT to red of the external speaker. The IN pin of the LM386 module connects to pin 5 (PB0) of the ATTiny, the two GND pins connect to GND and the VCC connects to VCC.

 

The code is very short and uses a lot of hardware settings which has been explained line-by-line in the comments (thanks to Łukasz Marcin Podkalicki). Upload the following sketch via the Arduino ISP programmer

#include <avr/io.h>

#include <avr/interrupt.h>

#include <util/delay.h>

 

#define  AUDIO_IN  PB3 //Physical pin 2

#define AUDIO_OUT PB0 //Physical pin 5

 

int

main(void)

{

  /* setup */

  DDRB |= _BV(AUDIO_OUT); // set AUDIO_OUT pin as output

  TCCR0A |= _BV(WGM01)|_BV(WGM00); // set timer mode to FAST PWM

  TCCR0A |= _BV(COM0A1); // connect PWM pin to channel A

  TCCR0B |= _BV(CS00); // set prescaler to 1

  ADMUX |= _BV(MUX0)|_BV(MUX1); // select ADC3 (PB3)

  ADMUX |= _BV(REFS0); // set internal 1.1V reference voltage

  ADMUX |= _BV(ADLAR); // left adjust of ADC result

  ADCSRA |= _BV(ADPS1)|_BV(ADPS0); // set ADC division factor to 8

  ADCSRA |= _BV(ADEN)|_BV(ADIE); // enable ADC and interrupt

  ADCSRA |= _BV(ADATE); // set ADC auto-trigger

  ADCSRA |= _BV(ADSC); // start conversion

  sei(); // enable global interrupts

 

  /* loop */

  while (1);

}

 

ISR(ADC_vect)

{

 

  OCR0A = ADCH; // the magic

}

 


Nokia 5110 LCD Display

The Nokia 5110 84x48 LCD graphics display was used on millions of mobile phones in the late 1990's and due to their simple connections they are easily integrated into electronics projects. They are inexpensive, versatile and are very reliable. They are available “as is” or can be purchased with header pins already attached.

 

 

Nokia 5110 LCD Module

 

To demonstrate the 5110 module, the following example collects data from an LM35 temperatyre sensor and displays the temperature on the 5110 screen. For TMP36 sensor ( which is capable to measure -50 - 100 Celsius ) there is a correction in the code to substract 0.5V from ADC reading. So if you want to use LM35 sensor you need to remove this line in the code.

 

Follow the pin out schemes below

 

LM35    (flat face facing)                ATTiny

Data pin (centre)                              pin 2 (PB3)

VCC (left)                                        VCC     

GND (right)                                      GND

 

Nokia 5110                                     ATTiny

RST                                                   5 (PB0)

CE                                                     GND

DC                                                    6 (PB1)

DIN                                                   7 (PB2)

CLK                                                  3 (PB4)

VCC                                                  3V

LIGHT                                              GND (for the backlight)

GND                                                 GND

 

Upload the following sketch via the Arduino ISP programmer

#include <avr/io.h>

#include <avr/pgmspace.h>

#include <stdint.h>

#include <stdlib.h>

#include <stdbool.h>

#include <avr/sleep.h>

#include <util/delay.h>

#include <avr/wdt.h>

#include <avr/interrupt.h>

 

/** Glyph data (stored in PROGMEM)

 */

extern const uint8_t SMALL_FONT[] PROGMEM;

 

// SMALL FONTS only fit into progmem

 

const uint8_t SMALL_FONT[] PROGMEM = {

  0x3e, 0x51, 0x49, 0x45, 0x3e, // 30 0

  0x00, 0x42, 0x7f, 0x40, 0x00, // 31 1

  0x42, 0x61, 0x51, 0x49, 0x46, // 32 2

  0x21, 0x41, 0x45, 0x4b, 0x31, // 33 3

  0x18, 0x14, 0x12, 0x7f, 0x10, // 34 4

  0x27, 0x45, 0x45, 0x45, 0x39, // 35 5

  0x3c, 0x4a, 0x49, 0x49, 0x30, // 36 6

  0x01, 0x71, 0x09, 0x05, 0x03, // 37 7

  0x36, 0x49, 0x49, 0x49, 0x36, // 38 8

  0x06, 0x49, 0x49, 0x29, 0x1e, // 39 9

  0x08, 0x08, 0x08, 0x08, 0x08  // 2d -

  };

 

// Nokia LCD pin numbers

#define LCD_MOSI  PINB2

#define LCD_SCK   PINB4

#define LCD_CD    PINB1

#define LCD_RESET PINB0

 

/** Number of columns */

#define LCD_COL 84

 

/** Number of text rows */

#define LCD_ROW 6

 

/** Transfer data to a slave (MSB first)

 *

 * @param sck the pin to use for the SCK output

 * @param mosi the pin to use for the MOSI output

 * @param data the data to transfer

 * @param bits the number of bits to transfer

 */

void sspiOutMSB(uint8_t sck, uint8_t mosi, uint16_t data, uint8_t bits) {

  uint16_t mask = (1 << (bits - 1));

  uint8_t output = (1 << mosi);

  uint8_t clock = (1 << sck);

  while(bits) {

    // Set data

    if(data&mask)

      PORTB |= output;

    else

      PORTB &= ~output;

    // Bring the clock high

    PORTB |= clock;

    // Move to the next bit

    mask = mask >> 1;

    bits--;

    // Bring the clock low again

    PORTB &= ~clock;

    }

  }

 

/** Send a data byte to the LCD

 *

 * @param data the data byte to send.

 */

void lcdData(uint8_t data) {

  // Bring CD high

  PORTB |= (1 << LCD_CD);

  // Send the data

  sspiOutMSB(LCD_SCK, LCD_MOSI, data, 8);

  }

 

/** Send a command byte to the LCD

 *

 * @param cmd the command byte to send.

 */

void lcdCommand(uint8_t cmd) {

  // Bring CD low

  PORTB &= ~(1 << LCD_CD);

  // Send the data

  sspiOutMSB(LCD_SCK, LCD_MOSI, cmd, 8);

  }

 

/** Write a single character

 */

 

void lcdPrintChar(uint8_t row, uint8_t col, uint8_t ch) {

 

  // Set the starting address

  const uint8_t *chdata = SMALL_FONT + (ch * 5);

 

    lcdCommand(0x80 | col);

    lcdCommand(0x40 | (row % LCD_ROW));

    // And send the column data

   for(uint8_t pixels = 0; pixels < 5; pixels++, chdata++) {

    uint8_t data = pgm_read_byte_near(chdata);

    lcdData(data);

    // for double sized font put

   // lcdData(data);

    };

  // Add the padding byte

// if(col < LCD_COL)

   lcdData(0x00);

  }

 

/* MAIN PROGRAM

*/

 

// Watchdog generated interrupt in program

// used for polling ADC data and displaying LCD info

//

ISR(WDT_vect) {

 

  // while interrupt do ADC and send output to LCD

        int temp;

        uint8_t firstdig;

        uint8_t seconddig;

  uint8_t low, high;

 

        ADMUX = _BV(MUX0)|_BV(MUX1); // ADC3

        ADMUX &= ~_BV(REFS0); // explicit set VCC as reference voltage (3V = 3000mV)

  // ADMUX |= _BV(REFS0); // 1.1 V reference voltage  by setting 1 to bit REFS0

  ADCSRA |= _BV(ADEN);  // Enable ADC

  ADCSRA |= _BV(ADSC);  // Run single conversion

  while(bit_is_set(ADCSRA, ADSC)); // Wait conversion is done

 

  // Read values from ADC

  low = ADCL;

        high = ADCH;

 

       // clear nokia LCD

    lcdCommand(0x80);

    lcdCommand(0x40);

    // Fill in the whole display with ZEROS

    for(uint16_t index = 0; index < (LCD_COL * LCD_ROW); index++)

     lcdData(0x00);

         

         // measure voltage from LM35 with VREF = 3000 mV

          temp =  (  (  ((high << 8) | low) * 3000UL) >> 10);

         // measure with internal Vref 1.1V, but it is not reliable when powering down 

         // temp =  ((((high << 8) | low) * 1100UL) >> 10);

 

         //  correction for LM36 - TMP36 readings -0,5V

     if (temp > 499) {

      temp = temp - 500;

    }

            else

                   {

                // display MINUS sign if temperature below zero

                        temp = 500 - temp;

                        lcdPrintChar(2, 30, 10);

      }

 

                firstdig = temp / 100;

        //        seconddig = (temp - (firstdig * 100))/ 10;

                seconddig = temp %10; 

 

               lcdPrintChar(2, 40, firstdig);

               lcdPrintChar(2, 47, seconddig);

              

         // ADCSRA &= ~(1<<ADEN); // switchoff ADC

      

}

 

int main(void)

{

 

          DDRB &= ~_BV(PB3); // set data pin as ADC INPUT

 

          // LCD INITIALIZATION

  /** Initialise the LCD

  *

  * Sets up the pins required to communicate with the LCD screen and then does

  * the actual chipset initialisation.

  */

   // Set up the output pins, ensuring they are all 'low' to start

   uint8_t val = (1 << LCD_SCK) | (1 << LCD_MOSI) | (1 << LCD_RESET) | (1 << LCD_CD);

   PORTB &= ~val;

   DDRB |= val;

   // Do a hard reset on the LCD

   //_delay_ms(10);

   PORTB |= (1 << LCD_RESET);

 

   // Initialise the LCD

   lcdCommand(0x21);  // LCD Extended Commands.

   lcdCommand(0xA1);  // Set LCD Vop (Contrast).

   lcdCommand(0x04);  // Set Temp coefficent.

   lcdCommand(0x14);  // LCD bias mode 1:48.

   lcdCommand(0x20);  // LCD Normal commands

   lcdCommand(0x0C);  // Normal display, horizontal addressing

 

          //set timer to 1 sec for measurements of LM35

           WDTCR |= (0<<WDP3) | (1<<WDP2) | (1<<WDP1) | (0<<WDP0);

 

          // set timer to 0.5s

          // WDTCR |= (1<<WDP2) | (1<<WDP0);

 

          // set timer to 4 sec

          // WDTCR |= (1<<WDP3);

 

          // Set watchdog timer in interrupt mode

          WDTCR |= (1<<WDTIE);

          WDTCR |= (0<<WDE);

         

          sei(); // Enable global interrupts

 

          set_sleep_mode(SLEEP_MODE_PWR_DOWN);

   

for (;;) {

    sleep_mode();   // go to sleep and wait for interrupt...

  }

}


No comments:

Post a Comment