In the last weeks, I have been working in a miniproject that consist on create a blinking effect in a led to simulate a flame. The result is a small board that can manage 8 leds outputs but can be easily scalable to have more outputs.
To get the flame effect in a led, you need to have a variable brightness in the led, and to get it you have to modify every a random time the intensity of the light with a random value. To get you have to modify the PWM of a led. You can get a more realistic effect using a dual led red-yellow.
Lets start by the hardware. I have used ATMEGA8515 because I had some samples at home but it is not the best choice. The hardware is really simple and only has the microcontroller, a voltage regulator, some high side drivers to manage the leds and some connectors.
Schematic
If you have an stable 5V external power supply you can remove the voltage regulator and mount R18 and Z1 instead of it. I'm using the voltage regulator, that is low drop, feed by 4 AA batteries, so I haven't R18 and Z1 mounted. Another point is the decision to use high drivers to manage the leds and the reason to use it instead of low side is to be able to manage dual leds. If you use a dual led (red-yellow) you can get a more realistic effect. I have added an oscillator in the system just in case I'd need to implement a UART communication, but I'm using the internal oscillator, so I haven't mount X1, C1 and C2.
Regarding the software I have modified the PWM values according the next constants.
VAR_DUTY is the variable duty cycle of each output and CONST_DUTY the constant duty cycle. In this case the software takes PWM value between 40 plus a random value between 0 and 20. The duty cycle is mesured in %.
VAR_WAIT is the variable time between 2 duty cycles changes and CONST_WAIT is the minimum time. We have a minimum time of 50 ms plus a random time between 0 and 50 ms. The times and duty cycles of the outputs are completely independent.
As the microcontroller doesn't have enough PWM outputs, I have managed them by software. Basically I have a list of duty cycle for each output and an interrupt. At the beginning of the cycle, starts all the outputs that are on, and calculates then next time that the driver has to change the state of a pin. Then depending on it, reconfigures the timer value to generate the next interrupt. The PWM is implemented in the file pwm.c and is easily scalable
Thisweek I havebeentriedtocreateanapplicationusingFreeRTOS as operatingsytem.
FreeRTOS is an operating system for embedded systems that provides a pre-emptive real time scheduler. Using FreeRTOS in an embedded software application allows the application to be structured as a set of autonomous tasks. The scheduler selects which task to execute at any point in time in accordance with events and the state and relative priority of each task.
You can visit the FreeRTOS web where you can find the source code and information about how to use it.
In the downloaded files you will find the FreeRTOS source files and the demo files. To do my testing I have use the AVR_ATMega323_WinAVR files from the demo folder. In my system I have a ATMega64 that is similar to the ARMega323 but it has some differences. In my demo I have called one task with a parameter but I have called twice times, with the parameter equal to zero the task turns a led off every one second and with the parameter equal to one turns the led on. There are a delay of half second beetwen both tasks.
To compile the software I have used AVR Studio. You only have to add the files to the source files and compile. To configure the system you have to follow the next steps:
Set the MCU definition
Set the correct clock frequency in the file FreeRTOSConfig.h
Check the configTOTAL_HEAP_SIZE definition that is the available RAM to be used by FreeRTOS.
Check the file Source/portable/GCC/ATMega323/port.c where there are functions that have to be adapted to each microcontroller.
So, the software needs to do at least the nexts steps.
Create the tasks with xTaskCreate. When you define a task, you define the priority, the needed parameters and the amount of memory for the stack
Call the function vTaskStartScheduler that starts the FreeRTOS. This task start the idle task that is a task done in background by the operating system.
The operating system provides APIs to manage the system as delays, start, stop o resume tasks, semaphores, queue or ticks.
Here is a picture of the 3D model that I have prepared.
To do it, I have used the program LEGO Digital Designer. This is an interesting tool to make LEGO models. In this case I have done a model using the classic LEGO bricks. The program can be downloaded from:
Then click on OK. The AVR Eclipse update site is now shown in the list of update sites. Select the "AVR Eclipse Plugin" and press the Install... button in the top right corner.
To setup the tool you have to follow the next steps:
goto to File->”new project”
select C/C++ , C++ project and next
choose a project name (Test_avr)
on project type select AVR Cross Target Project , Empty project, AVR-GCC Toolchain
press next, and on advanced settings, go AVR, AVRDude , programmer configuration, select HardProg, or you programmer name (named before), the press apply.
Here you can also configure the fuses, and other stuffs during the programing
Then on AVR, go to Target Hardware
Select you AVR, or simply press load MCU, and you will get the AVR type.
Press apply
Then go to: C/C++ Build -> Settings, on Additional tools in toolchain, and select Generate HEX file for Flash memory, and select AVRDUDE
On: C/C++ Build -> Settings, on AVR Compiler, on Optimization, select Moderate optimize (-o2)
Well, that's all. You can send me a mail if you have some question.
The software architecture of the main board is something like this.
Each box in the picture represents a software component that is named with a three letters acronym. The software is divided in three layers, application (APP), services (SRV) and drivers (DRV). There are also two layers in drivers. The layer bellow is the low level driver that manages the microcontroller peripherals and the layer above is a manager. We have also a services layer that gives services to the application like angle or arm positions calculations. I mean that make this kind of calculations.
We have also a diagnostic layer, which is not implemented yet and will be used to manage directly peripherals without the application and test the hardware. And also will be able to configure parameters.
Managing all the system we have an operating system that in fact is a scheduler. It uses a 1ms tick to count time. It have a list of task that can we configured how long have to launched and with which delay. I have added in the operating system the WinAVR libraries.
Let’s going to review the software components. For the time being the services that I have are:
ACL: This is the arm calculations module and from the ADC measurements of the potentiometers from the arm, calculates the arm angles and the hand position.
BVM: This module is the battery voltage manager. It has a task to be executed every 100 ms that takes the ADC measurement from the battery voltage, calculates the battery voltage and turns on the red led if the voltage is to low.
HPM: This is the hand pulses manager. It has a cyclic task to be executed every 1 ms and counts pulses from the hand encoder to know the position. I have planned to store the hand position in EEPROM but I haven’t implemented yet.
USS: This is the ultrasound manager that drives the I2C to read the distance measured by the sensors. It has a task to be executed every 50 ms and functions that returns the distances to the objects.
In the drivers layer we have:
ADM: This component manages the ADC converters. It has a task to be executed every 10 ms and for the time being measures the elbow position, shoulder position and battery voltage. This is done every 30 ms.
IOM: This is to configure and manage the input-output pins. It has functions that manage the leds and motors and drives each function to the adequate pin.
DCM: This component manages the DC motors. It has a cyclic task called every 10 ms and one instance for each motor. Each motor has its own configuration constants to configure the end of each movement. In the future these parameters would be in EEPROM and they will be calibrated. Also I’ll try to detect objects collisions but this will be in next versions.
ICM: This module is the I2C manager. It has the functions to start and read the ultrasound sensors measurement.
LCD: This is the display driver. It has the functions to initialize and to write in the display.
PAP: This module manages the stepper motors. It has a task to be executed every 1 ms
TCK: It has the functionality to manage the tick measurement. Initializes a timer and has a counter.
And the low level drivers:
ADC: Here we have the functions to manage the analogue-digital converters peripherals.
DIO: In this module we have the functions to configure and manage the digital input-output pins.
I2C: We have the functions to manage the I2C peripheral.
GPT: In this component there are the functions to configure and mange the general purpose timers.
Well, I have finished describing the available components. The next steps will be to develop more drivers like PWM or communications. The communications are important because I want to make software in a PC based on Linux to manage the robot. I have a board with an embedded Linux were I’ll try to put a software developed in the PC. The idea is to make all the drivers implemented in the ATMega64 board and the application in the embedded Linux board.
Now I'm going to do a review of the development environment and the tools that I'm using to the development.
The operating system I'm using is Windows but there are also tools that work with Linux. First of all is to choose the C compiler. I'm using AVR-GCC (WinAvr) that is a free compiler and it's very easy to use. You can go the web http://winavr.sourceforge.net/ where you can find the installation files and information about how to use it. I have installed the version 20090313 but you can download the newest one. In the web http://www.nongnu.org/avr-libc/user-manual/index.html there are information about the libraries and examples. To use it, only is needed to install the compiler.
The AVR Studio projects can be linked with AVR GCC. When you create the project you have to select the AVR GCC. You only have to choose the main file and the microcontroller. The program creates the makefiles and to compile you have to select the project files and just push the build button.
This debugger has a JTAG connector and can be linked to AVR Studio. You just have to connect to the board and you can debug directly from AVR Studio. If you are familiar with debuggers is very easy to use.
As it can see, is based on a ATMEGA64. The board has four L298, each of them has two full transistors bridges. Two of them manage the two stepper motors and with the other two it can manage up to four CC motors. The board has also a LCD connector were I have connected a 16x2 display. It has also some tension dividers to adapt the signals going to the ADC converters. I'm using two ADC converters to measure the arm angles trough a potentiometers and a third channel to measure the battery voltage. The hardware is also ready to measure the current consumption of the motors.
The board has a 40 pins connector were there are the ADC inputs, the motors, I2C to connect two ultrasound sensors and some general propose pins connected to the microcontroller. I have used 3 of these pins to put a encoder and measure the hand position.
The board has also three leds. To program I added a SPI connector, but when I tried to program the fuse bit the first time I failed and then it didn't work. Finally, I bought a JTAG programmer and I soldered some wires to the board to put the JTAG connector
Here is also the PCB design. The design has two layers.
Here is a photo of the board working. The board is hand made done, using a two layers board with a photo sensible material. The process to do it is print the photolytic in a transparent sheet, then you have to isolate the board in both layers, put it in a revealing and finally put it in an acid to remove the spare copper.
When I made the board, the first I did was to solder the main components to do it work like the microcontroller, oscillator, programming connector... Then I made a simple program to turn on the led and I programmed it. The picture was made after I performed the LCD driver and as it can see most of the components are not mounted.
In the next entrance I write about the programming environment, tools and how I did to program it. If you want more information, you want the schematic or whatever you need don’t hesitate to contact me.