To start, I will explain the major differences between microcontrollers, PIC and single-board computers. Then I will focus on the AVR family from Atmel and the tools that are avaialble to program them. The board I will be using will be the one manufactured during week 7.
This week is about embedded programming but I did some extra work related to production as well:
(D)esign is a vision of the future, a decision making process, an exploration of potential realities... while (d)esign is how to make it real today, using all the tools and techniques available.
Topics covered (course) Video recording (course) Video recording (recitation) Students and Labs My files
I completed the assembly of my DIY reflow oven and I used it with a first PCB. Two weeks ago, I had a issue with my PCB (the footing for the crystal was to small) and I had to create a new revision for this week. For the reflow ove, I followed this tutorial and here is how the final product looks like
The main advantage of this oven is that it follows the reflow temperature curve for the material used for soldering (lead or lead-free solder). Here is the one for the KESTER EP-256
The output looks surprising (I think the decoloration is related to the FR4 material) but it works perfectly. The board on the left is soldered manually and the one on the right comes out of the reflow oven
(from Wikipedia) AVR is a family of microcontrollers developed since 1996 by Atmel, acquired by Microchip Technology in 2016. These are modified Harvard architecture 8-bit RISC single-chip microcontrollers. AVR was one of the first microcontroller families to use on-chip flash memory for program storage, as opposed to one-time programmable ROM, EPROM, or EEPROM used by other microcontrollers at the time. AVR microcontrollers find many applications as embedded systems. They are especially common in hobbyist and educational embedded applications, popularized by their inclusion in many of the Arduino line of open hardware development boards.
I have been using the ATmega328 (the one installed on the Arduino Uno) for a while and I recently discovered the tinyAVR series with Fab Academy
To select an AVR, it depends on what you want to achieve and how much money you want to put on the table. For one prototype, any of them is definitely affordable (it varies from less than $1 to less than $20) but for mass production every cent count and there should ne no reason to overdesign. Here are some criteria to take into account (I know, my summary is oversimplified but I hope it helps) :
Before Fab Academy, I had no clue what PICs were and how to compare them with AVRs. Both have links to MicroChip Technology company. I found this comparaison and the conclusion is ... it depends what you want to achieve and the criterias I listed for AVRs are still valid for PICs. But Arduino guys may have change the big picture, especially for hobbyists when they clearly simplified the "getting on board" process in the embedded development world with their products (along with their IDE). For mass proudction, PICs may be a better choice, depending on what features you need and how you are confortable with development environment (that looks older by the way..) .
This is not part of the PIC topic but there is another family I heard about: the MSP and especially the MSP-430. The MSP430 is a mixed-signal microcontroller family from Texas Instruments. Built around a 16-bit CPU, the MSP430 is designed for low cost and, specifically, low power consumption embedded applications. They try to get some traction with hobbyists. See this link for a list of projects based on the MSP-430.
(from Wikipedia) A single-board computer (SBC) is a complete computer built on a single circuit board, with microprocessor(s), memory, input/output (I/O) and other features required of a functional computer. Single-board computers were made as demonstration or development systems, for educational systems, or for use as embedded computer controllers. Many types of home computers or portable computers integrate all their functions onto a single printed circuit board.Unlike a desktop personal computer, single board computers often do not rely on expansion slots for peripheral functions or expansion. Single board computers have been built using a wide range of microprocessors. Simple designs, such as those built by computer hobbyists, often use static RAM and low-cost 8- or 16-bit processors. Other types, such as blade servers, would perform similar to a server computer, only in a more compact format.
At EXFO (my day job), I'm using SBCs every day and most of our products are designed from customized SBCs. We are also using AVRs for peripheral controls and dedicated tasks (like energy management)
To illustrate what SBCs are vs AVRs, let's assume you want a blinking LED on your product. You could build a HW circuit (around a 555 timer for example) and that circuit would be perfectly reliable (since it has nothing else to do). You could use a GPIO port on a AVR and the advantage would be the fact that you can upload new SW in the chip if you want to change the blink rate for example. You could (but you should not..) rely on a SBC. But then you depend on multiple layers (driver, operating system, thread priorities, ..) and the probability to have a stable blinking frequency is quite low.
In the hobbyist world, Raspberry PI, BeagleBone and the SnapDragons are well known examples of SBCs. Note that both of them are ARM based architectures (like your phone but unlike you laptop .. unless you are a Chromebook fan).
A datasheet contains everything you want to know (and even things you thing you will never need to know.. ) about a HW part. I found the ATTiny44 datasheet on Microchip web site and I extracted some parts that will be useful for the challenge I will explain in the next section
I read tutorials from Sparkfun as well. There are tons of informaton there on how to hookup Atmel MCUs and to program them. Most of the information in the following lines come either from this site or from the datasheet
Here is what I want to achieve:
The LED is connected to port number 5 and to the GND through a resistor. To turn the LED On, the MCU has to set the port number 5 to HIGH
The button is connected to port number 6 and there is an HW pull-up to force it to HIGH unless someone push on the button (then it goes to LOW until the button is depressed)
I already have a working board (from week 7) and I know the FTDI communication works. I will start from there and add the missing use cases:
Two weeks ago, I programmed my board and the detailed procedure is here. The idea was to demonstrate the communication between the MCU and a terminal running on a PC
This week, I don't want to spend much more time on pure C (i.e outside of the Arduino environment) programming. But I have to demonstrate I can code someting in C langage and here it is. This is a very simple piece of code, along with the makefile, that makes the LED on my board .. blink
I think it could be usefull (based on questions I received...) for other students to document some concepts harder to understand. Here it is...
Macro in C langage. Nothing to do with Excel (or any other Sw) automated tasks some of you may know. The idea is the following. You write source code then the compiler (gcc) comes and it compiles it, ie. it transforms it into machine readable instructions. There is a step just before compilation where you can ask the pipeline to substitute some "text" with other "text". Here is an simple example
Note: there are more complex example where you may want to substitute an entire function along with the parameters. And one last thing you may ask: what is the advantage of a macro vs a constant to declare something like "the speed of the light" for example. Simple answer, defines do not take space in the memory at run time, constants (most of the time) do.
Makefile A makefile is kind of a receipt book that is used by the "make" utility. I found out this simple tutorial that will help to figure out. In our Labs, when we type "make fuses" it means, "Dear make utility, please search into the makefile an entry named fuses and execute whatever is listed under that tag. In the following makefile, it means executing the avrdude program with the parameters listed above.
Bitwise operator in C langage. n the C programming language, operations can be performed on a bit level using bitwise operators. To start, let's make clear what the difference is between "bit" and "bytes". "bit" is the smallest representation of a reality in the computer world. It has only two possible values: 0 or 1. "byte" is a set of "bits", most of the time 8. "byte" is used to represent a reality more complex than a bit. By convention (ASCII standard), a "A" character for example is represented by 01000001 in binary representation. Modern computers manipulates set of bits (could be 8, 32 or even 64) at a time, not one bit at a time. But on the other side, small AVRs (manipulating 8 bits at a time) have limited space and it makes sense to store multiple information in one single byte. Ok... but then why do we need bitwise operators (i.e acting at the bit level) ? Because we want to play (read or write) individual piece of information in a wider set of information. Let's have a look on the following statement in Neil's code (from here)
At line 197, there is a function call to set the pins for the Rx/Tx : set(serial_port, serial_pin_out);
There is a macro at line 25: #define set(port,pin) (port |= pin) // set port pin line
That transforms it into a bitwise operation : serial_port |= serial_pin_out
serial_port is (based on the other macro on line 34) equivalent to PORTA, which is a (8 bits) data register (according to the datasheet)
PORTA register controls whether a pin is HIGH or LOW
It is therefore équivalent to PORTA |= serial_pin_out
But there is another macro at line 38 that says #define serial_pin_out (1 << PA1)
It is therefore equivalent to PORTA |= (1 << PA1)
Still looking into the datasheet, we can figure out who is PA1. This is the port marked 12 on the HW representation)
The << symbol is a the "left bit shifting symbol" and here is what it does: it shifts each bit in its left-hand operand to the left by the number of positions indicated by the right-hand operand. But ... why so much pain and trouble ? Could we just set the value ?
No, and here is why: we are playing with individual bits, not decimal values. PA1 is defined in another .h file somewhere (iotnx4.h) as equal to 1. This is a decimal value, i.e 00000001 in binary representation. Thus, left shifting 0000001 by 0000001 gives 0000010... which is.. 2 in decimal
The last step is to apply the |= operator. Another programmer trick: it means "replace the content of the PORTA bit array by the result of the logical OR operation between the current value of PORTA and the value we just computed, i.e 0000010.
As a final result, we end up with an updated PORTA data register where the 7th bit is set to 1, all others remaining untouched
Note: at line 198, there is another instruction with a similar logic but with an effect on the DDR register that controls whether a pin is an input or an output
I'm familiar with the Arduino IDE for a while, mainly with Arduino UNO boards but if you are not, you should have a look on the following tutorial
I found out a library written by Spence Konde here . It helps a lot to program various AVR MCUs from the Arduino IDE. There are many ways to install it, I suggest to have a look to this tutorial but there are a few things to understand to have a clear view on the big picture:
As you can see, the pins to control the LED and the button are now D8 (digital 8) and D7 (digital 7). Setting D8 to HIGH should turn the LED on and here is the code to do it
We COULD take a different path from here. The first step is to burn a specific Bootloader that will help us later to program our MCU over the FTDI cable. Connect your ISP to the board and to your computer. Start the Arduino IDE, then open the Tools menu and select a programmer (mine is a USBASP). Then select a Board (ATTiny 24/4/84) and a Chip (ATTiny44). Click on Brn Bootloader and you should see an output similar to this one. You now have a working Bootloader. Type the dmesg command in a terminal and you should see
We have now a bootloader on the board. The MCU is also connected to another 6 pin connector that brings VCC, GND, Tx and Rx and we COULD use it to push our code directly using the FTDI cable and WITHOUT the ISP. But there is an issue: rigth of the bat, Arduino IDE does not know anything about our FTDI adapter... but AVRDUDE knows it, as you can see here (from /home/philippe/Documents/arduino-1.8.7/hardware/tools/avr/etc/avrdude.conf)
I will not spend more time on this but it looks it is possible. There is a file named "programmers.txt" in Arduino folders and this file set the list of supported ISPs. We could add an entry there... For the moment, I will stay on the ISP track
The next step is to create our code that the MCU will load and execute. Still using the Arduino IDE, create a new sketch. Do not change anything and click on Sketch, Uplaod to verify whether you can push code to the MCU.
Let's create another piece of code to manage the button. Two concepts are important here: debouncing and interrupts
Here is how the code looks like WITHOUT interrupts and WITHOUT debouncing
Here is how the code looks like WITHOUT interrupts and WITH debouncing
To leverage HW interrupts , we rely on the MCU specifications. Within the Hardware interrupt there are two categories: External interrupts and Pin Change Interrupts. The nomenclature here is confusing since all hardware interrupts are at first sight external. The only pin supporting external interrupts on the ATTiny44 is the pin 5 but we used it to connect the LED. In another board revision, it would make sense to use pin 5 for the button and pin 4 for the LED.
So we have to dig on the Pin change side. Each time an interrupt occurs, it triggers the associated ISR (Interrupt Service Routine) assuming you have turned that interrupt on. Each External Interrupt has its own ISR and they can be triggered independently by either a rising signal, falling signal, or by both. Note: the Pin Change Interrupts share an ISR between all the pins on a port (port B, C, and D). And anytime a pin changes on that port, it calls the port’s ISR which must then decide which pin caused the interrupt. So Pin Change Interrupts are harder to use but you get the benefit of being about to use any pin.
There are three steps to using Pin Change Interrupts.
Here is how the code looks like once everything is in place
Finally, let's wrap all this and implement the required features. Note: the SoftwareSerial library is conflicting with the Interrupt library, this is a known problem I don't want to investigate now. My fallback plan is to use the SW debouncing method
I'm definitely not a datasheet ninja but I understand where and what to look for
Two weeks ago, I made it work using Neil's code and this week I ran on my own with a simple scenario with a led, a button and a serial communication with a terminal
See here
I barely can keep the current pace with a new topic every week. Stay tuned...