The winter holidays are approaching and I thought of creating something interesting and in the spirit of these holidays using technology..
Last year I create a Christmas tree project: https://community.element14.com/challenges-projects/project14/holiday-special-2023/a/holiday-projects/HP29/christmas-tree-2023
In this year I decided to create something special for Christmas tree: a funny decoration.
The whole story started when I discovered this type of led matrix:
I bought one, I connect it to an Arduino Nano and I followed the configuration from this Sparkfun tutorial.
I downloaded the "Chaplex" library and "Sparkfun led array 8x7 Arduino" library; these libraries are attached to this project.
On Sparkfun site I found some fun projects; I attached the projects files. Hint: on Sparkfun site, search for BadgerHack for more information.
1. How decoration was madeAfter testing of several examples from Sparkfun library, I decided to develop this decoration, using EasyEDA for schematic/PCB and Arduino IDE for software.
I added an temperature sensor, MCP9700T, an reset button, 56 red LEDs, an power switch, crystal oscillator, programming connector, two CR3023 battery holders and other several components. The BOM is attached.
The result is this red Christmas tree decoration:
The features of this decoration are:
- can be programmed with a text of max 40 characters; this text will be scrolled on led matrix;
- can display temperature using sensor MCP9700T;
- can display some seasonal animations, like: snowing, a child on a sled, some Christmas tree decoration, etc.
All this can be selected using the double switch mounted on the front side.
To program the text that will be scrolled on led matrix, I used am BT module, HC-05 or equivalent of this, JDY-31.
2. Programming and upload the codeI developed the code using Arduino IDE because the examples for the 7x8 charlieplex led matrix are coded using Arduino IDE.
If the programming was some sow easy, MCU programming was more complicated due to an MCU selection error during the schematic and PCB development.
So, when I selected the MCU in the EasyEDA program, I did not pay much attention to the name of the selected MCU. My intention was to use ATMega328P, but when I created the wiring diagram of the de, I chose ATMega328PB.
The program was developed and tested on an Arduino Nano while the PCBs were being manufactured.
The problem appeared when the decoration PCBs came.
I was dying to program one, but the first surprise came: I couldn't program it because the Arduino IDSE couldn't communicate with the MCU on the decoration board. Then I noticed the difference and started looking for solutions to solve the problem.
After doing some research, I found two solutions to solve the problem:
- the first solution (the easy solution): to replace the microcontroller on the board with the ATMega328P (used in Arduino Nano);
- the second solution (more complicated and frustrating but more interesting and fun): to modify the Sparkfun library to be able to use ATMega328PB and to add support for MCU in Arduino IDE.
Obviously, I chose the second solution (more challenging!).
Before continuing, I would like to make a short comparison between ATMega328P (used in Arduino Nano) and ATMega328PB, used by me.
The ATmega328PB is generally compatible with the ATmega328P at the instruction level, but sometimes requires minor adjustments in the code when additional peripherals or added pins are used. Most libraries for the ATmega328P will work fine on the ATmega328PB.
Conclusion: the ATmega328PB is an expanded and more powerful version of the ATmega328P, great for projects that require more peripherals or more efficient power management.
Now, get back to our project.
So: the first step in using ATMega328PB with Arduino IDE is to ensure its compatibility with the development environment. To achieve this, we will need to install a specific package for the ATmega328PB.
This package name is MiniCore and can be found here.
First, add the MiniCore to the to the board manager in the Arduino IDE like this: open Arduino IDE, go to File > Preferences and add the following URL to Additional Boards Manager URLs:
https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json
Then install MiniCore (this a package with support for ATMega328PB): go to Tools > Board > Boards Manager, search for MiniCore and install it.
Now, config the Arduino IDE to use the ATMega328PB for this project: got to Tools > Board and select ATmega328; then perform the additional settings as in the above picture:
At this point we have to configure the programmer; this is: USBasp. I used this solution to program the MCU directly because I can not use the bootloader.
Obs: with bootloader, is another story. I flashed the MCU, using USBasp with Arduino Nano bootloader, using information from here; in the Arduino Nano schematics, to reset the MCU through CTS pin, an capacitor is connected between MCU Reset pin and CTS pin from FTDI; on my schematic, the capacitor used between FTDI and Reset pin from the board was not placed; even if I added it later, I still couldn't use the bootloader.
The USBasp will be connected to the decoration PCB ISP connector as in the following pictures:
At this moment, we have two option to use USBasp: from Arduino IDE, Upload button (from main UI) or from Arduino IDE, Sketch menu, Upload using programmer.
Important: in Arduino IDE, Tools, Programmer, USBasp should be selected!
Important: because we do not use the Arduino bootloader in this project, we have to set manually the correct fuse bits for this MCU ATMega328PB. To do that, we will open a windows cli and from there will write a command that will "invoke" AVRDUDE:
avrdude -C "C:\Users\mihai\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\etc\avrdude.conf" -c usbasp -p m328pb -U lfuse:w:0xFF:m -U hfuse:w:0xD9:m -U efuse:w:0xF7:m
Fuse bits are set for the following configuration:
- external clock for 16MHz;
- "brown-out" set at 1.8V;
- EEPROM retained at flash (but only if AVRDUDE is used; Arduino IDE will erase both program and eeprom memory);
- programming through ISP (Serial Programming) is allowed;
- WDT (Watchdog Timer) is disabled;
- MCU starts from first address after reset.
Now, for programming, we have two options:
1. using Arduino IDE, as above;
2. using AVDRUDE from Windows CLI.
If you have several decorations built (for gift of for your own use) and you want to program them, then you can use the second method, because it is much faster because it only writes the memory with the already generated hex file instead of compiling the sketch at each Upload from the Arduino IDE.
To achieve that, we have to do some extra steps.
First, we have to generate the hex file. For that, we have to press on Sketch, Export compiled binary. The hex file will be exported in the project folder, with a name like "name-of_the_project.ino_atmega328pb_16000000L.hex".
Second step is to use this file to flash the MCU, from Windows cli:
avrdude -C "C:\Users\mihai\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17\etc\avrdude.conf" -c usbasp -p m328pb -U flash:w:C:\Users\mihai\OneDrive\Documente\Arduino\Test_cu_328PB\Cod_10_final.ino_atmega328pb_16000000L.hex:i -U lfuse:w:0xFF:m -U hfuse:w:0xD8:m -U efuse:w:0xFF:m
OBS:
- this is a combined command, that will flash the hex file and then apply the fuse bits;
- the first path is location of AVRDUDE installed by the Arduino IDE;
- the the second path for hex file will be adjusted for your project location but ro not use spaces in the folders and files name;
- at the end of the command are the fuse bits.
3. How code is working and featuresThe main component of this Christmas tree decoration is the charlieplexed led matrix. On this we will display various information and pictograms.
The libraries used to display text or pictograms on this charlieplexed led matrix are created by Sparkfun for Arduino IDE and should be used with Arduino boards based on ATMega168, ATMega328 and ATmega328P. But nu design was created with ATMega328PB, so...what should I do in this case?
Well, I have 2 options: one is to change the MCU with one compatible with the library from Spatkfun and other is to adapt the library to use the definitions for ATMega328PB (from MiniCore definitions).
So, the modification that should be done in the library "SparkFun_LED_Array_8x7_Arduino_Library", in file "SparkFun_LED_8x7.cpp" is to add definitions for ATMega328PB; the modification should be done in two places: at the beginning of the file and at the bottom of the file:
#if defined __AVR_ATmega168__ || \
defined __AVR_ATmega328__ || \
defined __AVR_ATmega328P__ || \
defined __AVR_ATmega328PB__
The modified library is attached to this project.
After that I was able to compile the Sparkfun examples.
But after the first flash I realize another issue with the design: the led from PCB was flipped horizontally; this means that another change must be made in the library code:
//const charlieLed SparkFun_LED_8x7::charlie_leds_[] = {
// {0,1}, {0,2}, {0,3}, {0,4}, {0,5}, {0,6}, {0,7},
// {1,0}, {1,2}, {1,3}, {1,4}, {1,5}, {1,6}, {1,7},
// {2,0}, {2,1}, {2,3}, {2,4}, {2,5}, {2,6}, {2,7},
// {3,0}, {3,1}, {3,2}, {3,4}, {3,5}, {3,6}, {3,7},
// {4,0}, {4,1}, {4,2}, {4,3}, {4,5}, {4,6}, {4,7},
// {5,0}, {5,1}, {5,2}, {5,3}, {5,4}, {5,6}, {5,7},
// {6,0}, {6,1}, {6,2}, {6,3}, {6,4}, {6,5}, {6,7},
// {7,0}, {7,1}, {7,2}, {7,3}, {7,4}, {7,5}, {7,6}
// };
const charlieLed SparkFun_LED_8x7::charlie_leds_[] = {
{0,7}, {0,6}, {0,5}, {0,4}, {0,3}, {0,2}, {0,1},
{1,7}, {1,6}, {1,5}, {1,4}, {1,3}, {1,2}, {1,0},
{2,7}, {2,6}, {2,5}, {2,4}, {2,3}, {2,1}, {2,0},
{3,7}, {3,6}, {3,5}, {3,4}, {3,2}, {3,1}, {3,0},
{4,7}, {4,6}, {4,5}, {4,3}, {4,2}, {4,1}, {4,0},
{5,7}, {5,6}, {5,4}, {5,3}, {5,2}, {5,1}, {5,0},
{6,7}, {6,5}, {6,4}, {6,3}, {6,2}, {6,1}, {6,0},
{7,6}, {7,5}, {7,4}, {7,3}, {7,2}, {7,1}, {7,0}
};
OBS: on the top is the original led designation and on the bottom is the new LEDs assignation, to follow by hardware design.
Now, all the hardware/software issues was solved. We can move on to the code.
The decoration can display 4 different programs, based on the switch positions; the programs based on led position is displayed on the back of the PCB.
A. First program: display only temperature.
To display temperature, ambient temperature, I used am MCP9700T sensor. Because this device is powered from batteries, I used for ADC a internal 1,1V reference:
analogReference(INTERNAL); // for ATmega328 (1.1V)
B. Second program: display only message.
The message is displayed as a scrolling message, from left to right. The message is stored in internal EEPROM and can be updated via serial port, with 9600bps.
After the decoration is powered up, the specific function will check if is any message stored in EEPROM. If is not any message, then the buffer will be filled with a specific string and is displayed on led matrix: "No text saved in EEPROM".
The new message is sent over serial to the decoration and is processed by a specific function, that will save the message in EEPROM.
If you want to delete the message you have to sent this text over serial: "Delete_message" and the message will be deleted from EEPROM.
OBS: to update the message see point 4: Update text message.
C. Third program: display only pictograms.
The displayed icons are moving, from left to right or from top to bottom. These are:
- display snow;
- display a child on the sled;
- display small Christmas decoration (this will display only a 7x8 frame);
- display random snowflakes.
OBS: I wrote three more functions for displaying some icons, but they are commented, because the library that deals with displaying on the charlieplexed matrix consumes a lot of RAM memory; therefore, these three functions cannot run at the same time as the ones above, even if the sketch compiles successfully:
- display PacMan;
- display Christmas large decoration (this will display an Ax8 frame, where A is a line numbers and can be grater than 7lines);
- display a melting snowball.
D. Fourth program: display all the message together.
This program will display all available data on the display as follows:
- display temperature;
- display message;
- display snow;
- display a child on the sled;
- display small Christmas decoration (this will display only a 7x8 frame);
- display random snowflakes.
4. Update text messageDuring the programs and after startup, the decoration will send some information over serial port to outside (PC terminal, mobile phone with BT, etc.). For this project I used serial comunication via BT using "JDY-31 Bluetooth Module".
On mobile phone I used Android application named "Bluetooth Terminal HC-05":
On the decoration schematic/PCB I mounted two LEDs: one red is used to show serial data OUT and one green used from serial IN:
To use this BT module, first you have to pair it to the mobile phone; In the BT menu, you will see the "JDY-31-SPP device"; the default PIN code is 1234. All the data are in the attached datasheet:
After that, open "Bluetooth Terminal HC-05" mobile app and connect it to the BT module:
Press on the name of BT device and console application will be opened. From here we can monitor the running program and we can update the text that will be displayed on led matrix, using buttons.
Important: the string that is sent over BT console mast contain the string terminator character or LF (Line Feed). To do that, in the BT console app, you can long press on Btn1 to 5 of Send ASCII button and verify/check the option from below picture:
Note: after the message is updated, disconnect the BT module from the Christmas tree ornament to prevent rapid battery discharge (this module consumes quite a lot of current when operating).
5. Video demonstrationThe decoration will display all: text message, temperature and pictograms (SW1 =1 and SW2 = 1):
How the specific message is displayed if no text is saved in eeprom:
6. LimitationsA. The main limitation of this decoration is related to the batteries. I choose two CR2032 3V batteries connected in series, because are relativly cheap and easy to be replaced.
The decoration consume about 50mA at 5V. One CR2032 batterya has a capacity of about 210mAh (but for a current consumption less than 1mA).
A rough estimate of the capacity of the two batteries is:
(210mAh + 210mAh) / 50mA~= 8,4h
B. When the voltage on each battery drops below 2.5V, the BT module can no longer maintain the connection with the phone. that is why it is necessary that when the message is updated, the decoration must have new batteries.
C. Sometimes, if the text sent to the decoration over serial is long, an reset from the button is requiered becausr, due to the ram memory limitation, the mcu may stuck after the message is saved in eeprom memory.
Comments