This week I used the Arduino IDE as a programming environment. As I already installed the patch for ATtiny in week 6, I continued using an Arduino Uno with the ISP sketch to program the ATtiny via the serial peripheral interface (SPI). To familiarize yourself with the capabilities of the microcontroller, valuable information can be retrieved from its data sheet that is attached in the download section.
For here are the tasks for Week 08:
The best place to start reading the documentation is the first page of the data sheet which gives an overview about pinout of the microcontroller.
The ATtiny is equipped with two ports, port A (PA) and port B (PB). Port A has 8 I/O-pins (input/output) which can either be digital or analog. Port B has four I/O-pins. You can define the direction (I/O) for Port A and B via the data direction register (DDR) for the respective port, 1 will set it to output, 0 to input. By default, all pins are inputs (see page 66).
PB3 is the dedicated RESET to restart a program or automatically reset during a program download. From the pinout, you can also retrieve information on the other pins to be used for the SPI protocol during programming (MISO - PA5, MOSI - PA6, CKOUT - PB2, VCC, GND) as well as where to connect the crystal (XTAL1 and XTAL2) for an external clock. The crystal has to be connected to the XTAL pins with two 22 pF capacitor on each side (page 28). The ATtiny 44 has 256 bytes of EEPROM (tiny "hard drive"), 4 kBytes of In-System Flash Program Memory and 256 bytes of SRAM.
I used the board from week 6 and programmed a blink sketch in C using the second switch. From the schematics, one can see that PA7 is the input pin for the switch. The LED to be switch is connected to PB2.
Let me go trough the code briefly. Two libraries will be needed, the io library and the delay library. Furthermore the CPU clock speed needs to be set upfront. We will set it to the clock speed of the crystal which is 20 MHz.
The following function called switchLED switches the state of the LED based on the current stage. If the state is ON, it turns OFF and vice versa. So, we implement an if-condition, checking the level of Port B, pin 2 which is the third bit (counting starts a zero) in the PORT B register byte. 1 equals ON (high level), 0 equals OFF (low level).
The main function sets the direction registers and debounces the switch. By default, all pins are set to input, so the switch (which is an input) does not need to be initialized. I'm doing so still to remind myself doing it. The LED pin PB2 needs to be configured as an output by setting DDRA bit number 3 to 1 (again: pin count starts at zero).
After setting up the input and output, all the main function does is checking on the state of the button. I tried to check the bit state in the condition, but this did not work. Therefore, I used the existing method bit_is_clear from the io library. It tests whether a bit in IO register is clear and returns non-zero if the bit is clear and a 0 if the bit is set. In our case, the condition should be true, if the bit is set, so we have to inverse the return value of the function with the exclamation mark.
If we were be living in a perfect world, this would be sufficient. But the state of the button will toggle between pushed and released when it is pushed, so we have to give an interval after which a push is considered as such. Then, the second if-condition checks the level of PA7 again. The interval needs to be tweaked a bit. 100 ms worked pretty well. If the button state is still pushed after 100 ms the switchLED-function is called, switching the state of the LED.
The C code:
/*This is a blink sketch by Joern Kiwitt*/ #include <avr/io.h> #includ <util/delay.h> #define F_CPU 20000000UL #define LED_IO_PORT DDRB #define SWITCH_IO_PORT DDRA #define LED_OUTPUT_PORT PORTB void switchLED(){ //PB2 is LED Pin if(PORTB == 0b00000100){ //LED off PORTB = 0b00000000; } else if( PORTB == 0b00000000){ //LED on PORTB = 0b00000100; } } int main(void){ //set the LED DDR to output (PB2 on the ATtiny) LED_IO_PORT=0b00000100; //set the SWITCH DDR to input (PA7 on the ATtiny) - not necessary SWITCH_IO_PORT=0b00000000; while(1){ // Read button if(!bit_is_clear(PINA,PA7)){ // Bounce time _delay_ms(100); // Check that it was really pushed if(!bit_is_clear(PINA,PA7)) switchLED(); } } }
I uploaded the code using the Arduino as an ISP programmer connecting my board via SPI. Check my electronics production page for further details.
Demonstration switching ON and OFF