8. Embedded Programming¶
1. Resarch¶
As I’m an amateur on this topic, I will do something that really will help me: Learning from other’s documentation.
So I made a search in Fab Academy for ATTiny45 (as this is the processor that I’m going to use) and I found this interesting documentation of Abdelrahman Elshakankery.
This documentation has a really good link that says “How to Read a Datasheet“, that for me it suits me very good, as I’ve never read any Datasheet in my life. For example at the beginning expalins what a Datasheet is:
- Datasheet: are instruction manuals for electronic components. They (hopefully) explain exactly what a component does and how to use it. Unfortunately these documents are usually written by engineers for other engineers, and as such they can often be difficult to read, especially for newcomers. Nevertheless, datasheets are still the best place to find the details you need to design a circuit or get one working.
A good webpage about Demystifying the FabISP
2. Reading dathasheet (ATtiny45)¶
The link I used to learn more about the this micro controller is this website in PDF format.
This is a very cool video that shows the blinking process with an ATtiny45 in C with ArduinoUNO
3. Programming:¶
With Arduino:¶
Using AVR with the programmer¶
My lack of experience and my obfuscated mentality made me fail on this week. As I still don’t have any experience on this topic.
So I started to program using ArduinoUNO
Using USB cable¶
Programming my PCB:¶
As you might know from my Electronic design week, this PCB “Pepper” doesn’t have ISP for programming.
How did I programmed it?¶
Important note
This information is available as well in the Electronic design week.
What I wanted to do in the beginning was to use a programmer clip like this: |
---|
So what I did was to look for the PINOUT of the Attiny45 and the ISP of the programmer |
---|
And as well the position of the “teeth” of the clip |
---|
Once everything was clear, I “clipped” it |
---|
Unfortunatelly, it seems that I put too much soldering material. So the clip teeth’s got wasted, as it didn’t grab it well. |
---|
For this reason I had to go to another level and make a FRANKESTEIN.
I did this with the help of my instructor.
Basically, instead of having the connections between the MCU and the clip, I had to connect directly the pins to the MCU legs to the programmer.
Once everything was correct, I could program without any problem, because the connections didn’t have any problem.
We tested the blink LED first:
Programs:¶
So I tried three different programs. All of them were like “Echo-Helloing” (if I can say that):
-
The first one is the simple “Button pressed, LED blink”, that I have it explained in my design week.
-
The second one is whenever I pressed the Button, the program will write the letter “d”. And whenever I released the finger from the button, the program will write “u”. So let’s say it’s a “dududududu” program.
-
The third one is that whenever I open the serial monitor, and I type any letter it will say “hellow.ftdi.45.echo.c: you typed “(insert letter)”. Now the amazing thing here is that the programmer will saver/storage the letters one by one in the order that they were assigned. So you can basically write “strings” by using “chars”.
One thing that I need to clarify, is that all my codes have been written on “C” language
Did you know?
The C programming language is a great option for anyone wanting to write their own programs. It’s not limited by the hardware or operating system it runs on, and the simplicity of its features leaves room for optimization opportunities and extensions.
In other words, it is the BEST option for optimizing resources in your MCU.
Program 1:¶
Please visit my week Electronic Design to know about this program.
Program 2:¶
This program was given to me by my instructor Babken, who took it from Neil’s old code. Here I learnt more about how a code works and what things are useful when you want to code.
Here I changed some stuff, like the “bububu” type:
//
//
// hello.button.45.c
//
// button hello-world
// 9600 baud FTDI interface
//
// Neil Gershenfeld
// 10/31/10
//
// (c) Massachusetts Institute of Technology 2010
// This work may be reproduced, modified, distributed,
// performed, and displayed for any purpose. Copyright is
// retained and must be preserved. The work is provided
// as is; no warranty is provided, and users accept all
// liability.
//
#include <avr/io.h>
#include <util/delay.h>
#define output(directions,pin) (directions |= pin) // set port direction for output
#define input(directions,pin) (directions &= (~pin)) // set port direction for input
#define set(port,pin) (port |= pin) // set port pin
#define clear(port,pin) (port &= (~pin)) // clear port pin
#define pin_test(pins,pin) (pins & pin) // test for port pin
#define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
#define bit_delay_time 102 // bit delay for 9600 with overhead
#define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay
#define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay
#define input_port PORTB
#define input_direction DDRB
#define input_pin (1 << PB4)
#define input_pins PINB
#define serial_port PORTB
#define serial_direction DDRB
#define serial_pin_out (1 << PB1)
void put_char(volatile unsigned char *port, unsigned char pin, char txchar) {
//
// send character in txchar on port pin
// assumes line driver (inverts bits)
//
// start bit
//
clear(*port,pin);
bit_delay();
//
// unrolled loop to write data bits
//
if bit_test(txchar,0)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,1)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,2)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,3)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,4)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,5)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,6)
set(*port,pin);
else
clear(*port,pin);
bit_dela
And this is the result:
Program 3:¶
This program was, again, taken from Neil’s repository. It made me realize that a MCU can storage things, just like a pendrive. I’m saying “like”, because I know that its capacity in storage is limited, but what can you do wiht a simple ATtiny45 is extremely onto your imagination.
This is the code:
//
// hello.ftdi.45.echo.c
//
// tiny45 echo hello-world
// 9600 baud FTDI interface
//
// Neil Gershenfeld 11/17/19
//
// This work may be reproduced, modified, distributed,
// performed, and displayed for any purpose, but must
// acknowledge this project. Copyright is retained and
// must be preserved. The work is provided as is; no
// warranty is provided, and users accept all liability.
//
#include <avr/io.h>
#include <util/delay.h>
#define output(directions,pin) (directions |= pin) // set port direction for output
#define input(directions,pin) (directions &= (~pin)) // set port direction for input
#define set(port,pin) (port |= pin) // set port pin
#define clear(port,pin) (port &= (~pin)) // clear port pin
#define pin_test(pins,pin) (pins & pin) // test for port pin
#define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set
#define bit_delay_time 102 // bit delay for 9600 with overhead
#define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay
#define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay
#define serial_port PORTB
#define serial_direction DDRB
#define serial_pins PINB
#define serial_pin_in (1 << PB2)
#define serial_pin_out (1 << PB1)
#define max_buffer 25
void get_char(volatile unsigned char *pins, unsigned char pin, char *rxbyte) {
//
// read character into rxbyte on pins pin
// assumes line driver (inverts bits)
//
*rxbyte = 0;
while (pin_test(*pins,pin))
//
// wait for start bit
//
;
//
// delay to middle of first data bit
//
half_bit_delay();
bit_delay();
//
// unrolled loop to read data bits
//
if pin_test(*pins,pin)
*rxbyte |= (1 << 0);
else
*rxbyte |= (0 << 0);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 1);
else
*rxbyte |= (0 << 1);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 2);
else
*rxbyte |= (0 << 2);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 3);
else
*rxbyte |= (0 << 3);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 4);
else
*rxbyte |= (0 << 4);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 5);
else
*rxbyte |= (0 << 5);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 6);
else
*rxbyte |= (0 << 6);
bit_delay();
if pin_test(*pins,pin)
*rxbyte |= (1 << 7);
else
*rxbyte |= (0 << 7);
//
// wait for stop bit
//
bit_delay();
half_bit_delay();
}
void put_char(volatile unsigned char *port, unsigned char pin, char txchar) {
//
// send character in txchar on port pin
// assumes line driver (inverts bits)
//
// start bit
//
clear(*port,pin);
bit_delay();
//
// unrolled loop to write data bits
//
if bit_test(txchar,0)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,1)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,2)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,3)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,4)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,5)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,6)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
if bit_test(txchar,7)
set(*port,pin);
else
clear(*port,pin);
bit_delay();
//
// stop bit
//
set(*port,pin);
bit_delay();
//
// char delay
//
bit_delay();
}
void put_string(volatile unsigned char *port, unsigned char pin, char *str) {
//
// print a null-terminated string
//
static int index;
index = 0;
do {
put_char(port, pin, str[index]);
++index;
} while (str[index] != 0);
}
int main(void) {
//
// main
//
static char chr;
static char buffer[max_buffer] = {0};
static int index;
//
// set clock divider to /1
//
CLKPR = (1 << CLKPCE);
CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
//
// initialize pins
//
set(serial_port,serial_pin_out);
output(serial_direction,serial_pin_out);
//
// main loop
//
index = 0;
while (1) {
get_char(&serial_pins,serial_pin_in,&chr);
put_string(&serial_port,serial_pin_out,"hello.ftdi.45.echo.c: you typed \"");
buffer[index++] = chr;
if (index == (max_buffer-1))
index = 0;
put_string(&serial_port,serial_pin_out,buffer);
put_char(&serial_port,serial_pin_out,'\"');
put_char(&serial_port,serial_pin_out,10); // new line
}
}
And this is the result: