Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
We are using a Nordic nrf52840 chipset for our work - but really any number of Bluetooth boards should support this technique as we are really just using the advertising feature of BLE.
The Open Wireless Switch (OWS) system is designed to enable wireless communication between a switch (or button) and a central receiving device via Bluetooth Low Energy (BLE). This system is composed of two main components: the Advertisement (Switch Sending) board and the Central (Receiving) device. The switch board can enter pairing mode, send button press data, and enter sleep mode after a period of inactivity. The central device scans for BLE signals, pairs with the switch, and processes the button press data to simulate USB keyboard input or other actions.
The Advertisement board is responsible for sending BLE signals that represent button presses. It operates in two main modes: Pairing and Sending.
1. Pairing Mode
Activation: Pairing mode is activated when the Pairing button on the Advertisement board is pressed.
Behavior: When the device enters pairing mode, it wakes up from sleep and begins advertising a set of pairing packages. These packages contain specific data that allow the Central (Receiving) device to recognize and pair with the switch.
Purpose: Pairing mode is essential for establishing a connection between the switch and the receiving device. It allows the receiving device to identify the switch's MAC address and prepare for subsequent data transmission.
2. Sending Mode
Switch Depress (Button Press):
When a button (or switch) on the Advertisement board is pressed, the board begins to collect button press data. This data is organized into packages.
Each data package represents the state of the button over a period of 100ms. Within this timeframe, the button state is sampled at 10ms intervals, resulting in 10 button states per package.
The data packages are advertised (broadcasted) via BLE at a rate of one package every 100ms.
Inactivity & Sleep Mode:
After the button is released, if there is no further button activity for a specified period (default is 5 seconds), the Advertisement board will automatically enter sleep mode to conserve power.
In sleep mode, the device stops advertising and goes into a low-power state until it is reawakened by either another button press or the Pairing button.
The Central device is responsible for scanning for BLE signals from the Advertisement board, pairing with it, and processing the received button press data.
1. Pairing Mode
Scanning:
The Central device continuously scans for BLE devices in the vicinity. When it detects the pairing packages from the Advertisement board, it reads the MAC address and pairs with the device.
Pairing allows the Central device to recognize the specific switch and prepare to receive button press data.
2. Button Press Data Handling
Receiving Data Packages:
After pairing, the Central device begins to receive the advertised data packages from the Advertisement board whenever the button is pressed.
Each package contains the button states recorded over 100ms. These packages are transmitted and received in real-time.
Processing and Replay:
Upon receiving a data package, the Central device processes the button states contained within it.
The Central device can then replay these button states via USB as if they were keyboard inputs. This allows the button press on the switch to be translated into a corresponding action on the Central device, such as pressing a specific key on a keyboard.
The system is flexible, allowing the received data to be interpreted in different ways (e.g., as joystick input or other control mechanisms).
1. Manufacturer ID
Purpose: The Manufacturer ID is a unique identifier used in BLE advertising packets to distinguish the specific manufacturer or type of device. In the OWS system, this ID is used to identify the Advertisement board during the pairing process and when sending button press data.
Value: The Manufacturer ID used in the OWS system is 0xFFFF
.
Usage:
This ID is embedded in the BLE advertising packets sent by the Advertisement board.
The Central (Receiving) device listens for advertising packets with this specific Manufacturer ID to identify and pair with the switch.
The Manufacturer ID is included in every data package, allowing the Central device to verify the source of the received data.
2. Button Pair Packages
Purpose: The button pair packages are special BLE advertising packets sent when the Advertisement board enters pairing mode. These packages contain a predefined data structure that allows the Central device to recognize the board and establish a connection.
Package Structure:
The button pair package is a fixed-size byte array with the following structure:
Fields:
Bytes 0-1: Manufacturer ID (0xFFFF
).
Bytes 2-3: Pairing Identifier (0x9C7C
).
Bytes 4-19: Reserved for additional data or padding (all 0x00
in this case).
Functionality:
When the Pairing button on the Advertisement board is pressed, the board begins broadcasting these pairing packages.
The Central device scans for these packages and, upon detecting the correct Manufacturer ID and Pairing Identifier, will pair with the switch.
3. Button Press Data Packages
Purpose: The button press data packages are BLE advertising packets sent by the Advertisement board when a button is pressed. These packages contain recorded button states over a short period (100ms) and are used by the Central device to emulate input actions.
Package Structure:
Each button press data package contains the following fields:
Fields:
Manufacturer ID (Bytes 0-1): 0xFFFF
.
Package Index (Byte 2): A byte that increments with each new package, allowing the Central device to track the sequence of packages.
Button Data (Bytes 3-18): A 4x4 matrix where each row represents a different button, and each column represents a 10ms interval within the 100ms timeframe. Each entry in this matrix is a 4-bit value (0 or 1), indicating whether the button was pressed (1
) or not (0
) at that specific time interval.
Data Layout Example:
For a setup with 4 buttons, a data package might look like this:
Manufacturer ID: 0xFFFF
(Bytes 0-1)
Package Index: 0x01
(Byte 2)
Button Data:
Button 1 states over 100ms: 0x0A
(Byte 3)
Button 2 states over 100ms: 0x05
(Byte 4)
Button 3 states over 100ms: 0x03
(Byte 5)
Button 4 states over 100ms: 0x0F
(Byte 6)
Remaining bytes are padded with 0x00
for alignment.
Button States Interpretation:
Each button state byte can be interpreted as a sequence of bits representing the state of the button at each 10ms interval within the 100ms timeframe. For example, the byte 0x0A
(Button 1) could represent the following binary sequence:
This indicates that the button was pressed during the 4th and 2nd 10ms intervals and released during the others.
4. Buttons Configuration
Number of Buttons: The system supports up to 4 buttons by default, but this can be extended if needed by adjusting the data package format.
Button Identifiers:
Buttons are identified numerically (Button 1, Button 2, etc.).
Each button’s state is recorded separately in the data package, allowing the Central device to determine which button was pressed and when.
To try this out get two nrf52840 feather express boards from adafruit. Then load up the firmware for each board (its a arduino sketch - you want to first follow the guide here).
The firmware for the switch sending part is called advertisement. You need to add two switches - one for the actual switch (use a switch jack) and a tactile swich for pairing.
The firmware for the recievfing part is known as the central firmware. There should be defined a LED for indicating pairing. By default it's the red led of a nrf52840 Feather express.
When pairing button is pressed on the advertisement board it will send a specific pairing package and dongle receives this package and MAC address of the board it will listen for. The MAC is saved in flash memory and can be read later on start of dongle code.
Note - to save battery the advertisement board is set to sleep. Pressing the switch will wake it up - all in all this takes around 1 second.
So you can use a nrf52840 USB dongle to receive the switch press - or right now you could do it in software alone. See the python directory for this code.
When transmitting data, an nrf52840 dongle consumes around 1000 uA (1mA) In sleep mode, it consumes 20 uA. A Good coin cell battery can have around 200 mAh. So sleep battery life. 200mAh/20uA = 10000 hrs in deep sleep mode. 10000hrs > 416 days > a bit more than a year.
In transmitting: - Single press activates advertising, and if there is no next activity for half a second then advertising turns off. - So we have a consumption of 1mA during half second for a single press. So about Coin cell has 200 mAh -> 200 * 3600 mAsec or 7200 single presses.
How long will then a average coin cell battery last in sleep mode only?
500 mAh / 0.02 mA = 25,000 hours ≈ 1,042 days or about 2.85 years How long will the battery last in active mode only?
500 mAh / 1 mA = 500 hours ≈ 20.83 days”
But in general, cheap batteries will have less capacity.
If we have a 1000 mAh battery/ 0.02 mA = 50,000 hours ≈ 2,083 days or about 5.7 years sleep mode. Active mode only: 1000 mAh / 1 mA = 1000 hours ≈ 41.67 days
In our real world tests this stands up. We had our code running actively (a switch press per second) We calculated 3392945 switch presses in a total of 809hours approx 33 days. It was still going and we decided to read its battery voltage where we read 3.7. It starts at 4.2.
2532 uA (2.532 milliamperes) constant draw is seen on an HID connection with an nrf52840. So it consumes more than 2.5x more power.
Introduction
This project is very much experimental and work-in-progress. We have not yet all the aims of the work and may never get there. We hope though that key learning may be useful for others developing wireless switches in the future - HID or BLE advertisement.
There are a lot of various switches in existence. The typical connection for this has been a 3.5mm jack and socket. For a computer to understand this switch press, you require a box that turns this into something useful. This has typically been either a keypress, mouse press or a game controller button. Being tied to a lead can be a nuisance and risk for some people. We need a way of wireless switches existing. You can do this right now either using a form of Radio or Bluetooth - where several commercial switches and switch boxes exist and act as a Bluetooth Keyboard. But, this protocol can be both costly in respect of battery life and in overheads to support a Bluetooth keyboard.
Some companies have developed lower power switches using Bluetooth, but this is proprietary, and the technique is not open to allow others to use.
Define an open protocol for wireless switches that allows anyone to develop a switch for any system - and equally; software developers support the OWS standard
It should be as energy conservative as possible. People should expect a battery life of months and years - not hours and days.
It should work with no dongle on the receiving end. This is because many devices either have no port or it becomes difficult to access a port on a computer. But of course, having a dongle may be preferable and allow support to systems which can't/won't be supported
It should have a way of working with physical devices too
It should allow for 1+ multiple switches to use the same protocol
It should have documented the response times
It should be open to scrutiny and improvements from anyone
As of right now, we have working firmware for a Bluetooth chipset and software to receive the switches without the hardware. This is currently in python. We are open to discussion about the protocol and code.
Let's consider the different ways we can wirelessly create a switch (let us know if we have missed something!)
Technique | Pros | Cons |
---|---|---|
LoRa - Radio e.g 433
Low low Low power
You would need a sender and receiving dongle.
IR
Low power
Unreliable, needs a dongle to receive and send
Chirp/Sound
Low power ?
Now hard to do this as Spotify bought chrip. Could design your own thing.. but environmental noise? Unreliable? Fiddly on designing receiving code
Bluetooth HID
Ubiquotous, Receiving easy
Power hungry. A lot of wasted bandwith
Bluetooth Beacon
Low Power, Recieving straightforward
Need a dongle on some devices where a background task can't run (e.g. iOS)
Will Wade, With a big nod to Prente Romiche/Saltillo and their aeroswitch. Note - I have no idea if there's does exactly the same as this but a big clue was the fact they called it "Broadcast mode"
Our small team truly appreciates every contribution made by our community: user stories, feature requests, bug reports, and especially pull requests!. If you have any questions please reach out to our Core team at AceCentre.
Before we get into the full-blown "proper" way to do a pull request, let's quickly cover an easier method you can use for small fixes. This way is especailly useful for fixing quick typos in the docs, but is not as safe for code changes since it bypasses validation and linting.
Sign in to GitHub
Go to the file you want to edit (eg: this page)
Click the pencil icon to "Edit this file"
Make any changes
Describe and submit your changes within "Propose file change"
That's it! GitHub will create a fork of the project for you and submit the change to a new branch in that fork. Just remember to submit separate pull requests when solving different problems.
Loosely based on this great Gist by Chaser324
We like to keep a tight flow when working with GitHub to make sure we have a clear history and accountability of what changes were made and when. Working with Git, and especially the GitHub specific features like forking and creating pull requests, can be quite daunting for new users.
To help you out in your Git(Hub) adventures, we've put together the (fairly standard) flow of contributing to an open source repo.
Whether you're working on the API or the App, you will need to have your own copy of the codebase to work on. Head to the repo of the project you want to help out with and hit the Fork button. This will create a full copy of the whole project for you on your own account.
To work on this copy, you can install the project locally according to the normal installation instructions, substituting the name acecentre
with the name of your github account.
If you're doing more work than just a tiny fix, it's a good idea to keep your fork up to date with the "live" or upstream repo. This is the main acecentre repo that contains the latest code. If you don't keep your fork up to date with the upstream one, you'll run into conflicts pretty fast. These conflicts will arise when you made a change in a file that changed in the upstream repo in the meantime.
When using git on the command line, you often pull and push to origin
. You might have seen this term in certain commands, like
or
In this case, the word origin
is refered to as a remote. It's basically nothing more than a name for the full git url you cloned the project from:
is equal to
A local git repo can have multiple remotes. While it's not very common to push your code to multiple repo's, it's very useful when working on open source projects. It allows you to add the upstream repo as another remote, making it possible to fetch the latest changes straight into your local project.
When you want to update your fork with the latest changes from the upstream project, you first have to fetch all the (new) branches and commits by running
When all the changes are fetched, you can checkout the branch you want to update and merge in the changes.
If you haven't made any commits on the branch you're updating, git will update your branch without complaints. If you have created commits in the meantime, git will step by step apply all the commits from upstream and try to add in the commit you made in the meantime. It is very plausible that conflicts arise at this stage. When you've changed something that also changed on the upstream, git requires you to resolve the conflict yourself before being able to move on.
::: danger Conflicts You should always favor changes on upstream over your local ones. :::
Whenever you begin working on a bugfix or new feature, make sure to create a new branch. This makes sure that your changes are organized and separated from the master branch, so you can submit and manage your pull requests for separate fixes/features more easily.
::: warning Up-to-date Make sure to update your master branch with the one from upstream, so you're certain you start with the latest version of the project! :::
Prior to opening your pull request, you might want to update your branch a final time, so it can immediately be merged into the master branch of upstream.
::: warning Make sure to check if your branch is up to date with the master
branch of upstream. An outdated branch makes it near impossible for the maintainers of acecentre to check and review the pull request and will most likely result in a delayed merge. :::
Once you've commited and pushed all the changes on your branch to your fork on GitHub, head over to GitHub, select your branch and hit the pull request button.
You can still push new commits to a pull request that already has been opened. This way, you can fix certain comments reviewers might have left.
::: tip Please allow the maintainers of upstream to push commits to your fork by leaving the "Allow edits from maintainers" option turned on. This allows our Core Team to help out in your PR! :::
The main thing to be aware of when submitting a new acecentre feature request, is our rule on edge-cases. To keep the acecentre core codebase as clean and simple as possible we will only consider adding features that at least 80% of our user-base will use. If we feel that less than 80% of our users will find the feature valuable then we will not implement it. Instead, those edge-case features should be added as Extensions.
Before adding a new request, you should also first search to see if it has already been submitted. All feature requests should include the enhancement
label, so you can filter by that. And remember to also check closed issues since your feature might have already been submitted in the past and either rejected or already implemented.
Also, if you want to see the most highly requested features you can sort by :+1:
(the thumbs-up emoji).
If your idea passes the 80/20 test and has not already been submitted, then we'd love to hear it! Submit a new issue using the Feature Request template and be sure to include the enhancement
label. It's important to completely fill our the template with as much useful information as possible so that we can properly review your request. If you have screenshots, designs, code samples, or any other helpful assets be sure to include those too!
You can also vote on existing feature requests. As mentioned above, the :+1:
and :-1:
are used for sorting, so adding one of these reactions to the GitHub issue will cast a vote that helps us better identify the most desired (or undesired) features. And remember to add a comment if you have additional thoughts to help clarify or improve the request.
Our core team is always working hard to implement the most highly-requested community features, but we're a small team. If you need the feature faster than we can provide it, or simply want to help improve the acecentre platform, we'd love to receive a pull-request from you!
Pretty much any nrf52840 that you can load an arduino sketch onto. E.g.
SEEED XIA0 nrf52840. Super small - will take a lipo if you solder onto the back batt pins
Adafruit nrf52840 express. A great develeopment board. Has a spare button for you to use as either a pairing button or sending button.
Adafruit itsybitsy nrf52840. Same as the feather - but smaller and slight less flashy
And for the dongle
This is nice as its all in one piece. nrf52840 USB key