In a previous post, I talked about interfacing an Arduino with the HC-SR04 ultrasonic distance sensor. This time, I will do the same, but using an ATtiny84 and C code – no Arduino hardware or libraries.
In a previous post, I talked about serial communications with an ATmega168. But that chip has USART – hardware support for serial communications. But what about the tinyAVRs? As continuation of my last post on setting up the ATtiny84 for programming, this time, I will talk about sending data from an ATtiny84 to a computer using serial communications.
Like many folks, I got introduced to microcontrollers through the Arduino platform. The ease of setup, simple language syntax and the availability of a huge number libraries makes Arduino a very attractive choice to prototype your hardware projects. But after you get a grip on your project, sometimes it’s worth asking if you really need the power and the prototyping ergonomics of an Arduino, especially if all you are doing is reading a few sensors and turning on a few LEDs.
Atmel has a line of microcontrollers called tinyAVR which are little microcontrollers which can do a lot of the work that an Arduino does in a much more compact form. Take a look at the wikipedia page that compares the capabilities of the tinyAVRs.
Most times your microcontroller is running in a loop, waiting for something to happen – like a button press. All this while it is consuming power, and this could be an issue, especially if you are running the circuit from a battery. To counter this problem, there are ways of reducing the power consumption of your chip. Here are the various “sleep modes” supported by the ATmega168.
[Table reproduced from Atmel ATmega168 datasheet for illustrative purpose]
In a previous post about an Ambient Light sensor using an Op-Amp Comparator, I mentioned that we would be using the op-amp output to “wake up” an ATmega168. So here, we will be using the “power-save” mode from the above table, and use a pin-change interrupt to wake up from this sleep mode.
The setup used is shown below in the 2 schematics I had posted before. The output Vo from the op-amp should be connected to the pin 14 of the ATmega168 (PCINT0/PB0). Also, in this case, we are not using serial output, so you can remove the connections to the FTDI adapter.
Here is what the circuit looks like, hooked up on a breadboard:
This is the how the program works:
- When the program starts, start the 16-bit timer, set to fire an interrupt every 3 seconds. Start the timer only if pin 14 is low. (This means that the light level is high in our sensor circuit.).
- When the chip is not sleeping, it will be flashing an LED attached to pin 6.
- When the 16-bit timer interrupt happens, set a flag (a volatile variable) so that the main loop reads this flag and puts the chip to sleep mode. It will also turn the LED off at this point.
- Set up a pin change interrupt on PCINT0 for any logical change in input. When the interrupt fires, if it was caused by a rising edge (ie., light to dark), wake up the chip, and stop the 16-bit timer. If the interrupt was caused by a falling edge (ie., dark to light), re-start the 16-bit timer.
You can read about pin-change interrupts and the 16-bit timer in the Atmel ATmega168 datasheet.
The complete code listing is below. The opening comments in the code also have all the required build commands.