Often, many novice arduisers, “fired up” with the idea of mastering this device, buy an Arduino set and play a little do not know what to do with it next.
The author of this homemade product received an Arduino set by winning a homemade competition. Since then, the kit lay idle and he had little idea where it could be used.
At the same time, the master has a 2-year-old son who constantly presses buttons on a microwave oven, TV, etc. Once again driving his son away from the microwave, he thought that he could use the Arduino starter kit to make an electronic panel that would distract the child's attention from household appliances and at the same time serve for general development.
Let's watch a demo.
-LGB LED Arduino module;
-Robotdyne 4-digit 7-segment display module;
-LED matrix module 8×8;
-Keyboard module 4×4;
-4 tactile buttons; -Membrane alphanumeric keypad 4×4; -Battery level indicator; -4 toggle switches; -30 screws M2x10; -4 screws M3x5; -Jumpers; -Breadboard or Arduino expansion board; -Two lithium-ion batteries 18650 with holder; -Connector and DC plug 2.1/5 DC; -Charging module 2S BMS; -11 LEDs with a diameter of 3 mm, different colors; -4 resistors 220R
-Laser cutter; Step one: concept
A rough idea of how large the panel should be to accommodate all the components is a prerequisite.
The original idea was to model the control panel after the avionics of an aircraft: the three instrument panels are connected to the main body with M2 screws. Each panel will have slots for components: an LED matrix and keyboard on the left, a 7-segment display and several LEDs in the top center, and an LCD screen with a rotary knob, joystick and some buttons on the right.
Initially, all LEDs in the design are like stand-alone and segment/matrix displays – it was supposed to be connected via GPIO expansion modules to Arduino. As it turns out, the GPIOs in these devices do not provide enough current to power the LED. All LEDs must be connected directly to the Arduino.
As you can see in the top right corner of the diagram, the original design had room for four backlit touch buttons. The center dashboard also has cutouts for them (four small cutouts at the very top). However, these modules turned out to be not very user-friendly. In addition, the cutouts were too close together to accommodate the four modules, so the craftsman threw them away completely. Many more changes were made during the development of the Arduino software, so the diagram shown here is just an illustration of the general concept of this control panel.
Step two: the case
To design the case, the master used FreeCAD Part Design and Sketcher. The body consists of nine parts:
In FreeCAD, the design of a part begins with a sketch. Each panel is drawn when viewed from above, with all edges, cutouts and screw/fastener holes, and then extruded along the axis.
Once all the panels have been designed, you can move them using the FreeCAD Transform operation, which allows you to move the part along each axis and rotate it as needed. Everything is done in 3D, so it's a great way to see how the parts will look and fit together.
Since the parts of the body will be cut on a laser cutter, the craftsman added fittings, but for greater strength, the body will also be assembled using screws.
Threaded posts for attaching the lid to the box are installed in the corners of the case.
The master covers the walls of the box with stain.
Drawings for cutting the body parts can be downloaded below.
kids control panel cutout drawings.svg third: assembly
Now that the case is ready, you can assemble the device.
Since this project relies heavily on the I2C interface, the wizard starts with it. The Arduino Uno has I2C pins on both individual pins and A4/A5 pins. The wizard suggests using separate pins – P3.1 and P3.2 on the diagram. All I2C devices must also be powered, so all four lines (SCL, SDA, + 5V, and GND) must be connected to the I2C breakout board (or breadboard). These lines should go both to the GPIO expansion modules (GPIO_A and GPIO_B for simplicity) and to the ADC module.
Both GPIO expansion modules must have reset and address pins connected. Reset is an active low pin, so it must be connected to + 5V (preferably through a resistor). The address pins must be configured so that both devices can operate on I2C at different addresses, that is, they can be distinguished from each other. The master set the address contacts on GPIO_A to zero (all are connected to ground), and on GPIO_B to one (A0 is connected to + 5V, the rest to ground). These settings are translated to I2C addresses 0x20 and 0x21, respectively. The default address for the ADC module is 0x48, so there will be no conflicts here.
Pins A and B of the rotary encoder must be connected to pins 2 and 3 of the Arduino Uno.
The RGB LED module must be connected to the PWM-capable pins (marked with “~” on the Arduino board). PWM allows dimming.
Power for the 7-segment display, power for the LED array, and the second Arduino (Arduino B as shown in the diagram; those that drive the LCD screen) are connected via switches.
There are also two momentary toggle switches (ON-ON). One is used to turn on the battery level LED, the other is connected to ground and serves to reset the Arduino A.
A dedicated four-color LED strip uses 3mm color LEDs connected to separate pins on the Arduino via 220R resistors.
Most of the components are glued and/or screwed to the front panel. Both the Arduino and power-related stuff (battery cells, battery protection board, power cut-off board) are installed inside the case. The RGB LED module is also installed (glued in this case) inside, just below the 4×4 keyboard module. The distance between the keyboard PCB and the LED itself is approximately 2cm, so the RGB LED illuminates the entire PCB.
The second Arduino Uno – Arduino B – only connects to the LCD TFT screen. Please note that all eight data lines, all pins of the SPI interface and + 5V and + 3.3V must be connected.
Step four: programming
Given the set of components used, the master has planned the following panel features for Arduino A:
Display characters from the alphanumeric keyboard on the 7-segment display
Turn on the LEDs on the 8×8 matrix when keys are pressed on the 4×4 keyboard
Display some patterns with the colored LED strip
Using the four tactile buttons to switching modes of operation of the joystick and encoder:
control the led strip
control the color of the RGB LED
control LEDs on an 8×8 matrix
Since the Arduino B only connects to a TFT LCD, it will run a kind of drawing application.
There are very few custom hardware components here so most of the software will be handled by the Arduino libraries. Libraries used:
Encoder – for rotary encoder
Adafruit MCP23017 – for GPIO expanders
TM1637 for 7 segment and LED matrix modules
Keyboard – for all kinds of keyboards (the library is versatile enough to work correctly even with the four tactile buttons used here)
Adafruit PCF8591 – for ADC module
MCUFRIEND_kbv – for control LCD TFT display, including touch screen
Wizard added some custom skins for some of these libraries.
Skin for RGB LEDs
This wrapper is used to provide a high-level interface for controlling an RGB LED, including converting Cartesian XY coordinates to red-green-blue values.
class RgbLed & # 123; private & # 58;/* data */uint8_t pin_red; uint8_t pin_green; uint8_t pin_blue; protected & # 58; Color color; void setRGB (void); uint32_t hsv2rgb (uint16_t hue, float saturation, float value); public & # 58; RgbLed (uint8_t pin_red, uint8_t pin_green, uint8_t pin_blue); ~ RgbLed (); void setColor (rgbled & # 58; & # 58; Color color); void lighten (uint8_t amount); void darken (uint8_t amount); void changeBrightness (int delta); Color getColor (void); uint32_t rectToRGB (float x, float y); };
The code snippet below shows the use of the Arduino atan2 function. Angle calculation is performed only when the joystick is tilted in any direction (coordinates from the joystick are floating in the range -1..1).
if (abs (x) & gt; 0.1 or abs (y) & gt ; 0.1) & lt; br & gt; & # 123; theta = atan2 (y, x) + PI; } float ro = sqrt (x * x + y * y);
The function responsible for converting an angle to a color coordinate.
auto cval = & # 91; & # 93; (float theta, float ro, float phase, float neg_phase) & # 123; & lt; br & gt ; float val = sin (0.666 * theta - phase); if (val & lt; 0) val = sin (0.666 * theta - neg_phase); return val; };
float r = cval (theta, ro, -PI/2, PI); & lt; br & gt; float g = cval (theta, ro, 0 , 3 * PI/2); float b = cval (theta, ro, PI/2, 5 * PI/2); Color c = Color (r, g, b);
The display shell supports functions that convert the raw characters received from the keyboard into the raw bit values needed by the display libraries to actually display the character.
const uint8_t digitToSegment & # 91; 16 & # 93; = & # 123; & lt; br & gt; //XGFEDCBA 0b00111111, //0 0b00110000, //1 0b01011011, //2 ...
All keyboards are connected via GPIO, which excludes the use of their own functions. Overloading the pin_mode (), pin_read () and pin_write () methods in a subclass allows you to override their behavior to use GPIO extenders rather than native Arduino functions, without having to change any behavior in the parent class.
PanelKeypad (Adafruit_MCP23017 * gpio, char * userKeymap, byte * row, byte * col, byte numRows, byte numCols) & lt; br & gt; & # 58; Keypad (userKeymap, row, col, numRows, numCols) & # 123; PanelKeypad & # 58; & # 58; gpio = gpio; } void pin_mode (byte pinNum, byte mode); void pin_write (byte pinNum, boolean level) & # 123; if (PanelKeypad & # 58; & # 58; gpio! = NULL) & # 123; PanelKeypad & # 58; & # 58; gpio- & gt; digitalWrite (pinNum, level); }} int pin_read (byte pinNum) & # 123; if (PanelKeypad & # 58; & # 58; gpio! = NULL) & # 123; return PanelKeypad & # 58; & # 58; gpio- & gt; digitalRead (pinNum); } else & # 123; return -1; }}
LED strip shell
void move_bar (int direction) & lt; br & gt; & # 123; //make sure that direction is either 1 or -1 if (direction! = 0) & # 123; direction = direction/abs (direction); LedBar & # 58; & # 58; leds & # 91; led_ptr & # 93; =! LedBar & # 58; & # 58; leds & # 91; led_ptr & # 93 ;; LedBar & # 58; & # 58; color (led_ptr, LedBar & # 58; & # 58; leds & # 91; led_ptr & # 93;); if (direction & gt; 0) & # 123; ++ led_ptr% = numColors; } else if (direction & lt; 0) & # 123; if (led_ptr == 0) led_ptr = numColors; led_ptr--; }}}
This code transfers all logic operations to the joystick, and also masks the fact that the joystick is connected to an external A/D converter.
class Joystick & lt; br & gt; & # 123; public & # 58; Joystick (Adafruit_PCF8591 * adc, uint8_t pinx, uint8_t piny); Joystick (uint8_t pinx, uint8_t piny); float getX (bool update_coords = true); float getY (bool update_coords = true); bool isTilted (float threshold = TILT_THRESHOLD, bool update_coords = true); int getDirection (float axis_coords, bool update_coords = true); protected & # 58; Coordinates coords = & # 123; 0}; void read (); private & # 58; uint8_t pinx = 0; uint8_t piny = 0; Adafruit_PCF8591 * adc = NULL; float read_pin (uint8_t pin); };
The joystick module is essentially a two-axis potentiometer. The X and Y pins of the joystick module output voltage scaled from GND (0) to VCC (in this case + 5V), where 0 and + 5V correspond to the maximum tilt on either axis. Because of this, the joystick in the inoperative position gives out 0.5 * VCC at the X and Y pins.
The Joystick :: read () method reads the voltage from pins X and Y and converts the result to a floating point number in the range -1..1:
auto convert = & # 91; & # 93 ; (int value, uint16_t size) & # 123; & lt; br & gt; float x = (((float) value/size) - 0.5) * 2; return x; };
The Arduino sketch itself is a simple initialization of the required objects with their configuration performed in the setup () function. Loop continuously reads all inputs (keyboards, joystick, encoder), updates a shared variable that contains the position of the encoder, calculates the direction of its movement and calls handlers for screens, LEDs, etc.
if (current_mode = = RGB_LED_MODE) & lt; br & gt; & # 123; #ifdef RGB_LED_CONNECTED rgb_led_handler (joy_sw, delta); #endif led_bar.move_bar (1); } else if (current_mode == LED_BAR_MODE) & # 123; led_bar.move_bar (delta); } else if (current_mode == LED_MATRIX_MODE) & # 123; led_matrix_handler (); } else if (current_mode == LCD_MODE) & # 123; }
The wizard tried to use one Arduino Uno to handle all the inputs/lights and the LCD TFT screen, but this proved to be quite difficult, mainly due to the limited number of pins available. The LCD TFT screen requires both a 5-wire SPI (touch) and an 8-wire parallel data interface (display). All of these pins must be shared with other input devices.
Arduino B launches the tftpaint application, from the MCUFRIEND_kbv library, unchanged. This is a basic drawing application that allows you to draw points using several predefined colors.
You can download the code for it here.
Everything is ready. In the future, the master plans to modernize the panel. In particular, he plans to update the software and add one or more simple games for logic, attentiveness and reaction to the device.