OpenFlap
OpenFlap copied to clipboard
The OpenFlap project aims to create a open source, affordable split-flap display for the makers and tinkerers of the world.
OpenFlap
DISCLAIMER:
This is still a work in progress. Using the the code and files in this repository to create your own display is not recommended at the moment!
The OpenFlap project aims to create a open source, affordable split-flap display for the makers and tinkerers of the world. This repository houses all the required files to build and program your very own split-flap display. Currently we only support rectangular display configurations. Each display module has 48 characters. The files to produce a basic (alphanumerical) character-set are provided, as well as the resources to produce your own characters sets.
In this document I will layout the steps required to build an exemplary 5 wide, 2 high display.
Requirments (E.g.: 5x2 display)
Tools:
- soldering iron
- 3D printer
- torx T9 screwdriver
- idc crimp tool
- PICkit 4 for flashing the display modules
- 3.3V serial cable for flashing an ESP32
- ( optional 6704ZZ bearings )
Components
- OpenFlap Controller (1 per display)
- OpenFlap Top_Connector (1 per column E.g.: 5)
- OpenFlap Module (E.g.: 5x2 = 10)
- idc cables 6.5cm (1 per column E.g.: 5)
- A 12V DC power supply with 5.5mm barrel jack
Building an OpenFlap Display
Module
The modules consist of multiple 3D printed parts, sandwiched between two PCB's. Only one of those PCB's should be populated with components.
All required production files are available in /hardware/side_panel, /hardware/flaps and /hardware/encoder_wheel.
To make one module, you will need:
- 48 flaps ()
- 1 populated side panel
- 1 unpopulated side panel
- 2 encoder wheels
- 32x M2.6x8mm screw
- 1x 12V 60RPM MicroMotor
- 1x motor shaft coupler
When ordering these parts form JLCPCB, their webpage might report errors on the flaps and encoder wheels because they do not contain any "copper layers". You must manually provide this info in the UI:
- flaps : 49mm x 35mm, 0.8mm board thickness, Remove Order Number!
- encoder wheel: 74mm x 74mm, Aluminum base material, Remove Order Number!
3D print these parts, this should be possible without supports:
- The shell
- The core OR The core for use with bearings
- The long hub
- The short hub
- Assemble the flaps and the core in between the two encoder wheels. The printed side of the encode wheels must face outside. Make sure the orientation of the flaps in regard to the core is correct. The motor should be able to fit in the left side when the letters are facing you. Also note that the outer holes and the inner holes of the encoder wheels do not align in each position, make sure they do when you fasten them.
-
Slide the motor through the large bearing and attach the shaft coupler.
-
Solder the motor onto the populated side of the side panel in such away that the '+' symbol on the motor matches the '+' symbol on the backside of the PCB. Apply solder to the solder bridges marked with the white stripes. If the motor where to turn with an incorrect direction, the solder bridges should be swapped to. Use 4 screws to attach the large bearing to the side panel.
-
Use 4 screws to attach the small bearing to the unpopulated side panel.
-
Insert the core into the shell and sandwich in between the two side panels.
Controller
The controller hosts a webpage through which the display can be used. The webpage should be accessible through http://openflap.local/. The controller provides an access point on SSID: OpenFlap
with a default password: myOpenFlap
. Through the webpage, the controller can be configured to join your local network. (Reboot required)
All required production files are available in /hardware/controller. You might want to solder on horizontal SMD header pins in order to connect your serial cable for programming.
Top Connector
You will need 1 Top Connector and 1 idc cable for each column in your display. The Top Connector provides power to the column of displays. in this way the displays don't all require their own power circuitry. The board also helps to rout the data through the modules and back to the controller.
All required production files are available in /hardware/top_con. Additionally you will need to add the following components manually:
- 2x8 pin 2.54mm, low-profile, bottom-entry Header Socket
- 2x 2x8 pin box header
- 2x 2x8 pin idc Female Connector
- 6.5cm / 2.5" 16 strand flatcable
- 2x M2.6x8mm screw
The notch of the connectors on the cable should point in the same direction. Either both left or both right. The cable length should be around 6.5cm or 2.5".
Design choices
Encoder + DC motor
Traditional split-flap displays use stepper motors and a homing sensor to know it's starting position. OpenFlap uses a combination of an optical encoder and a DC motor. This allows the OpenFlap system to boot without having to do a homing rotation to know it's position. Additionally a dc motor is cheaper and simpler to drive.
Automatic data routing
The modules and top_con boards feature a smart switching mechanism that automatically routes the uart data signal. This reduces the amount of wiring required.
Each module and top-con board contains an input that when pulled low, interrupts the default data return path and continues the data path to the next module instead. This is shown in the image above in red (interruped signal path) and green (not interrupted signal path).
Construction
The construction of the OpenFlap module consist of PCB's and 3D-printed parts. Only one of the PCB's is populated. The characters and encoder wheels are also PCB's but they only have solder mask and silkscreen layers and no copper layers.
Power
Each module requires 5V for the micro controller and other low voltage components and 12V to power the motor. The top connector boards contain a 12V to 5V buck convertor to power each column. In this way, the modules don't need their own power circuit.
Local Webpage
Development Environment
A VS Code devcontainer is provided in this repository.
To flash the controller form inside the devcontainer you will need to forward your serial cable, see the README.md.
I was unable to work with the PICkit 4 from inside the devcontainer. You can compile the hex files and flash the from your host machine using MPLABX IPE.
Uart Interface Controller <--> Module
The OpenFlap modules communicate over uart at a baud rate of 115200 bps. The modules are daisy chained, meaning that the TX of the previous module is connected to the RX of the next module. There are 4 different types of commands:
- No operation
- Read property from all modules
- Write property to single module
- Write property to all modules
Value | Definition | Data Bytes |
---|---|---|
0x01 | firmware_property | 66 |
0x02 | command_property | 1 |
0x03 | columnEnd_property | 1 |
0x04 | characterMapSize_property | 1 |
0x05 | characterMap_property | 200 |
0x06 | offset_property | 1 |
0x07 | vtrim_property | 1 |
0x08 | character_property | 1 |
0x09 | baseSpeed_property | 1 |
Controller HTTP API
Endpoints:
- /api/modules
- /api/wifi
- /firmware
modules
A http GET request on the /api/modules
endpoint returns a JSON array containing all module properties.
[
{
"module": 0,
"columnEnd": true,
"characterMapSize": 48,
"characterMap": [" ", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "€", "$", "!", "?", ".", ",", ":", "/", "@", "#", "&"],
"offset": 0,
"vtrim": 0,
"character": "L"
},{
...
}
]
Try it with curl: curl -X GET http://openflap.local/api/modules
To write data to the modules, a http POST request can be used. The body of the request should be formatted in the same way as the response from a GET request. You only need to add module
index and the properties which you want to update.
Try it with curl: curl -X POST http://openflap.local/api/modules -H 'Content-Type: application/json' -d '[{"module":0,"character":"O"}]'
wifi
To change the used wifi credentials, a http POST request must be made to the /api/wifi
endpoint.
Use these credentials for the hosted access point.
{
"host":{
"ssid": "my_ssid",
"password": "my_password",
}
}
Use these credentials to connect to an existing an access point.
{
"join":{
"ssid": "my_ssid",
"password": "my_password",
}
}
A reboot is requeued for these changes to take effect.