Employment
Welcome to the employment hub for Phipps Electronics, here you will find positions we are currently looking to hire for, if you see a role you would like to apply for, please use the form at the bottom of the page to apply.
If there are no advertised jobs of interest, you can still send through your information for consideration for future roles, to do this, select “Interest for future positions” from the JOB ID drop down.
Increase your Linear Power Supply’s Current Capacity
Would you like to increase the current capacity of your power supply circuit? Not sure how to implement this? Read the rest of the article to find out.
Introduction
Power supply circuits are a good way to learn about electronics. They have different circuit configurations that make you explore things. Along with this, you learn new parts from different manufacturers. Consequently, you can always upgrade your power supply circuit when a need arises.
Increasing the current (or power) capacity of your power supply is a good place to start your upgrades. For example, if you’ve built a 1-ampere variable power supply, you could only use this for small hobby projects. You wouldn’t be able to use this for power circuits or motor-driven applications.
Fortunately, there is a way to upgrade your power supply circuit. You may need to replace some components though, as you’ll see later. You may also need to add a pass transistor to effectively increase the current capacity of your circuit.
Power Supply Blocks
In the previous article, the blocks of a basic linear power supply were discussed. This includes the following:
- Step-Down Stage
- Rectification Stage
- Filtering Stage
- Regulation Stage
- The Load
First, it’s wise to design your power supply with future upgrades in mind. Consider buying a more expensive Step-Down transformer with a higher current capacity. For example, if you’re just working on sub-1-ampere projects for now, you can already buy a 3-ampere transformer instead of limiting yourself to a 1-ampere transformer.
The same goes true for your Rectification stage. There are 3-ampere rectifier diodes available that you can use instead of using 1-ampere limited diodes. Make sure that you don’t exceed the Reverse Peak Voltage of your diode by having this value higher than the peak voltage your transformer can generate. See the chart below.
Your filtering stage is composed of a bulk filter capacitor. The size and capacitance of this capacitor can be increased. Increase its capacitance directly proportional to your targeted maximum current flow. A good formula to use is:
Capacitance = Maximum Current / (full-wave rect freq * Voltage ripple)
Where:
Capacitance is in Farrad
Maximum Current is the max current draw of your power supply depending on your load.
Full-wave rect freq is 2 x AC freq. If you have a 60Hz AC line then this equals to 120Hz.
Voltage ripple is your allowed ripple voltage. See the diagram below:
It’s important to note that the regulation stage usually has a regulator chip installed. The 78XX series of voltage regulator chips usually need 2 to 3V of voltage drop across them. This means your ripple voltage should be substantial enough to satisfy this value.
You may need the Voltage Peak value to complete the computation. Voltage peak is the root mean square multiplied by your transformer voltage value. If you have a 12V transformer, this equals (square root of 2) x 12V = 1.414 x 12V = 16.97 V.
For example, a 1V voltage ripple is allowed to happen so that a practical real-world capacitance value can be achieved. With a maximum load current of 3A:
C = 3A / 120 Hz (1V)
= 25000 uF
Use 27,000 uF or greater value.
If you only want a 0.5V voltage ripple:
C = C = 3A / 120 Hz (0.5V)
= 50,000 uF
Use 50,000 uF or greater value.
The Working Voltage of the capacitor can be made far above the transformer’s peak voltage.
WV of capacitor = 25V
The 2 to 3V voltage drop across the 7812 voltage regulator is satisfied through:
V input min = Vreg + 3V drop = 12V + 3V = 15V
For the 1V ripple:
V input max = 16.97V – 1V = 15.97V
For the 0.5V ripple:
V input max = 16.97V – 0.5V = 16.47V
Adding a Pass Transistor
The 78XX voltage regulator usually cannot handle currents in excess of 1 A. If you are going to use your power supply to supply 3A max, use a pass transistor for this. Pass transistors increase the current output of any regulated voltage output. Here is a simple example of a simple pass transistor configuration taken from a 7812 datasheet:
The pass transistor used here is a BD536. The BD356 has a maximum (absolute max) collector current of 8A. Make sure to connect a large heatsink for large collector currents and stay well below the maximum value.
As you can see, a resistor R1 is used to divert a part of the output current to the voltage regulator IC. The regulator’s current is the sum of Vbe/3 ohms plus the base current of Q1. The base current of Q1 is computed with its collector current divided by its Beta. Transistor Q1 may not conduct if the load demands are small, thereby letting the regulator IC supply all the current. This case is especially true if Ireg x R1 does not meet the Vbe needed to turn on transistor Q1.
Consequently, if you’re going to use a different pass transistor, verify the Beta and Vbe at different collector currents to achieve more reliable computations.
There are a wide variety of power components and blocks that you can use for your projects at Phipps Electronics:
Build a Simple LED/Fan Speed Controller for your ESP32 device
Have you tried playing with your ESP32’s PWM peripheral? Would like to control things like LEDs or PC Fans? Read the rest of the article to find out.
Introduction
Your ESP32 device is not just equipped with advanced networking and wireless functions, it’s also packed with several peripherals that you can use to control things. An excellent example of this peripheral is the PWM. PWM stands for Pulse Width Modulation. There are two kinds of PWM peripherals on the ESP 32 – Motor Control PWM and LED PWM. The LED PWM module will be tackled in this article.
What is LED PWM?
As its name implies, LED PWM is a peripheral on ESP32 that controls LEDs. However, it could also be used on a variety of applications. These applications include fan speed control, voltage regulation, and the like. The user can adjust the frequency, duty cycle, and resolution of the PWM signal through code. Consequently, Here is what the LED PWM controller of the ESP32 looks like:
In total, there are 16 PWM channels available. These channels can be mapped to the different GPIO ports of the device which are not engaged with other functions. Four high-speed timers control the high-speed channels and another four controls the low-speed channels. You can use different combinations of PWM frequencies and resolutions. Some common ones are listed below for your convenience.
It is also possible to fade the LED outputs by using the hardware resource from the LEDC controller. Consequently, you may need some RTOS knowledge to effectively use this feature. Otherwise, you can use software techniques for this, although it can eat up some CPU cycles.
How to Use LED PWM?
The Circuit
Your ESP32 devkit’s built-in LED can be used to demonstrate PWM. Otherwise, you can wire up a resistor and an LED on an empty GPIO port if your devkit doesn’t have one.
Get a small PC Fan, a 12V power supply, some transistors, and resistors for the fan speed controller. You can wire them up on a breadboard. You can choose to use bipolar transistors or a MOSFET as a fan driver.
For BJT transistor Fan Driver
- 1 pc. TIP 31C
- 1pc. 2N3904
- 1pc resistor – 10k
- 1pc resistor – 150 ohms
- 1pc 1N4001 (Back-EMF protection)
For FET FAN Driver
- 1 pc. FQP30N06L
- 1pc resistor – 470 (gate resistor)
- 1pc resistor – 10k (pull-down gate resistor)
- 1pc 1N4001 (Back-EMF protection)
BJT Transistor-type FAN controller
FET type FAN Controller
The Program
Before making an Arduino program for your ESP devices on the Arduino IDE, make sure you’ve read ESP32 on the Arduino IDE.
Introduce some definitions for the GPIO Pins, PWM channels, and the PWM resolution to use. After that, declare a constant variable MAX_DC for the maximum possible PWM duty cycle:
#define LED1 2
#define FAN1 4
#define PWM_CH_LED 0
#define PWM_CH_FAN 1
#define PWM_RES 8
const int MAX_DC = (int)(pow(2, PWM_RES) - 1);
Next, initialize the LEDC module in the setup part of your Arduino code using the ledcSetup and ledcAttach Pin statements:
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("PWM Program");
// PWM CH 0 (LED)
// 5 kHz freq
// 8 bit resolution
// attached to GPIO 2
ledcSetup(PWM_CH_LED, 5000, PWM_RES);
ledcAttachPin(LED1, PWM_CH_LED);
// PWM CH 1 (FAN)
// 5 kHz freq
// 8 bit resolution
// attached to GPIO 4
ledcSetup(PWM_CH_FAN, 5000, PWM_RES);
ledcAttachPin(FAN1, PWM_CH_FAN);
// kick start the FAN
ledcWrite(PWM_CH_FAN, MAX_DC);
delay(1000);
}
The code has an LED and a FAN part. Note that the FAN needs some initial “kick” to make it continue to turn without making it stall.
Here is the function prototype for ledcSetup()
And here is the function prototype for ledcAttachPin:
In the main loop, use the ledcWrite() function inside a for-loop to change the duty cycle of the PWM for both the LED and the FAN.
void loop() {
// put your main code here, to run repeatedly:
Serial.println("Run Software Fader");
uint8_t i;
for(i=0;i<MAX_DC;i++)
{
ledcWrite(PWM_CH_LED, i);
ledcWrite(PWM_CH_FAN, i);
delay(10);
}
}
Put a delay inside the for-loop so you can notice the PWM changes.
Here is the complete code:
#define LED1 2
#define FAN1 4
#define PWM_CH_LED 0
#define PWM_CH_FAN 1
#define PWM_RES 8
const int MAX_DC = (int)(pow(2, PWM_RES) - 1);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("PWM Program");
// PWM CH 0 (LED)
// 5 kHz freq
// 8 bit resolution
// attached to GPIO 2
ledcSetup(PWM_CH_LED, 5000, PWM_RES);
ledcAttachPin(LED1, PWM_CH_LED);
// PWM CH 1 (FAN)
// 5 kHz freq
// 8 bit resolution
// attached to GPIO 4
ledcSetup(PWM_CH_FAN, 5000, PWM_RES);
ledcAttachPin(FAN1, PWM_CH_FAN);
// kick start the FAN
ledcWrite(PWM_CH_FAN, MAX_DC);
delay(1000);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("Run Software Fader");
uint8_t i;
for(i=0;i<MAX_DC;i++)
{
ledcWrite(PWM_CH_LED, i);
ledcWrite(PWM_CH_FAN, i);
delay(10);
}
}
And here is a video of the circuit in action.
Note that you will see the PWM waveform change in time with the fading of the LED and turning of the FAN.
Find out more ESP32 devices and accessories that you can buy at Phipps Electronics:
Turn Your Bluefruit Feather into a Wireless Media Controller
Want to wirelessly control multimedia functions on your TV, PC, or Tablets? You can easily create a project out of this using your Feather. See the rest of the article to find out.
Introduction
Multi-media remote controllers have a niche market. You can find them being sold in different electronics shops online. They’re a favorable accessory, especially for the coach potato who likes to control things with his electronic remote wand. Consequently, don’t you know that you can build a remote media controller out of a Feather board? Continue reading the next parts of this article to find out.
The Human Interface Device (HID)
HID stands for Human Interface Device. It’s an interface designed for PCs that allows devices to interact with humans to extract valuable data. Examples of such devices are the mouse and keyboard. All of these devices’ inputs usually come from the person using them. These inputs are then used by your PC to process some operations. This HID Class was born out of the USB (Universal Serial Bus) specification.
The Bluetooth HID Profile
Since Bluetooth is a wireless protocol and HID is usually a wired USB specification, Bluetooth HID acts like a wrapper for the HID Class of devices using Bluetooth. Your Feather board, the 32u4 Bluefruit LE, can provide the BLE HID profile and many other pre-defined Bluetooth profiles. Consequenlty, included in the HID Class are the Consumer Control Keys. These keys can be used for multimedia functions, system control, application launchers, and browser-specific keys.
How to Make a Media Controller out of your Feather
The 32u4 Adafruit Bluefruit LE Feather board perfectly matches this job. You can define the Feather’s BLE module profile with an HID Consumer Control Keys class. With this, you’ll be able to control several multimedia functions on your PC and even on your smartphones or smart TVs as well if they support this class.
First, insert tactile buttons on a breadboard to connect to your Feather’s digital I/Os pins. Define the buttons as:
Button1 – Play/Pause
Button2 – Home
Button3 – Volume+
Button4 – Volume-
You can add several more HID Control Keys if you like. Listed below are other functions you can try:
– BRIGHTNESS+
– BRIGHTNESS-
– PLAYPAUSE
– MEDIANEXT
– MEDIAPREVIOUS
– MEDIASTOP
– VOLUME
– MUTE
– BASS
– TREBLE
– BASS_BOOST
– VOLUME+
– VOLUME-
– BASS+
– BASS-
– TREBLE+
– TREBLE-
– EMAILREADER
– CALCULATOR
– FILEBROWSER
– SEARCH
– HOME
– BACK
– FORWARD
– STOP
– REFRESH
– BOOKMARKS
Creating Code
You may use as base code the example code for hidcontrolkey under Adafruit nRF51 Bluefruit LE.
Here the code will be edited to take in 4 presses from buttons which relates to the defined HID consumer keys Play/Paus, Home, Volume Up, and Volume Down.
The whole code is found here:
/*********************************************************************
This is an example for our nRF51822 based Bluefruit LE modules
Pick one up today in the adafruit shop!
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
MIT license, check LICENSE for more information
All text above, and the splash screen below must be included in
any redistribution
*********************************************************************/
/*
This example shows how to send HID Consumer Control Keys,
ncluding the following control key definitions:
System Control (works on most systems: Windows/OS X/Android/iOS)
- Sound Mute
- Brightness Increase, decrease
Media Control (works on most systems)
- PlayPause
- MediaNext
Application Launchers (works mainly on Windows 8/10)
- EmailReader
- Calculator
Browser Specific (Firefox, file explorer: mainly on Windows 8/10)
- Back
- Forward
- Refresh
- Search
*/
#include
#include
#include "Adafruit_BLE.h"
#include "Adafruit_BluefruitLE_SPI.h"
#include "Adafruit_BluefruitLE_UART.h"
#include "BluefruitConfig.h"
#if SOFTWARE_SERIAL_AVAILABLE
#include
#endif
// define buttons
#define button1 A3
#define button2 A4
#define button3 A0
#define button4 A1
/*=========================================================================
APPLICATION SETTINGS
FACTORYRESET_ENABLE Perform a factory reset when running this sketch
Enabling this will put your Bluefruit LE module
in a 'known good' state and clear any config
data set in previous sketches or projects, so
running this at least once is a good idea.
When deploying your project, however, you will
want to disable factory reset by setting this
value to 0. If you are making changes to your
Bluefruit LE device via AT commands, and those
changes aren't persisting across resets, this
is the reason why. Factory reset will erase
the non-volatile memory where config data is
stored, setting it back to factory default
values.
Some sketches that require you to bond to a
central device (HID mouse, keyboard, etc.)
won't work at all with this feature enabled
since the factory reset will clear all of the
bonding data stored on the chip, meaning the
central device won't be able to reconnect.
MINIMUM_FIRMWARE_VERSION Minimum firmware version to have some new features
-----------------------------------------------------------------------*/
#define FACTORYRESET_ENABLE 0
#define MINIMUM_FIRMWARE_VERSION "0.6.6"
/*=========================================================================*/
// Create the bluefruit object, either software serial...uncomment these lines
/*
SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN);
Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN,
BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN);
*/
/* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */
// Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN);
/* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */
Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);
/* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */
//Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO,
// BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS,
// BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);
// A small helper
void error(const __FlashStringHelper*err) {
Serial.println(err);
while (1);
}
/**************************************************************************/
/*!
@brief Sets up the HW an the BLE module (this function is called
automatically on startup)
*/
/**************************************************************************/
void setup(void)
{
while (!Serial); // Required for Flora & Micro
delay(500);
// prepare button inputs
pinMode(button1, INPUT_PULLUP);
pinMode(button2, INPUT_PULLUP);
pinMode(button3, INPUT_PULLUP);
pinMode(button4, INPUT_PULLUP);
Serial.begin(115200);
Serial.println(F("Adafruit Bluefruit HID Control Key Example"));
Serial.println(F("---------------------------------------"));
/* Initialise the module */
//Serial.print(F("Initialising the Bluefruit LE module: "));
if ( !ble.begin(VERBOSE_MODE) )
{
error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?"));
}
Serial.println( F("OK!") );
if ( FACTORYRESET_ENABLE )
{
/* Perform a factory reset to make sure everything is in a known state */
//Serial.println(F("Performing a factory reset: "));
if ( ! ble.factoryReset() ){
error(F("Factory reset failed!"));
}
}
/* Disable command echo from Bluefruit */
ble.echo(false);
//Serial.println("Requesting Bluefruit info:");
/* Print Bluefruit information */
ble.info();
// This demo only works with firmware 0.6.6 and higher!
// Request the Bluefruit firmware rev and check if it is valid
if ( !ble.isVersionAtLeast(MINIMUM_FIRMWARE_VERSION) )
{
error(F("This sketch requires firmware version " MINIMUM_FIRMWARE_VERSION " or higher!"));
}
/* Enable HID Service */
//Serial.println(F("Enable HID Services (including Control Key): "));
if (! ble.sendCommandCheckOK(F( "AT+BLEHIDEN=On" ))) {
error(F("Failed to enable HID (firmware >=0.6.6?)"));
}
/* Adding or removing services requires a reset */
//Serial.println(F("Performing a SW reset (service changes require a reset): "));
if (! ble.reset() ) {
error(F("Couldn't reset??"));
}
Serial.println();
Serial.println(F("**********************************************************"));
Serial.println(F("Go to your phone's Bluetooth settings to pair your device"));
Serial.println(F("Some Control Key works system-wide: mute, brightness ..."));
Serial.println(F("Some are application specific: Media play/pause"));
Serial.println(F("**********************************************************"));
Serial.println();
}
/**************************************************************************/
/*!
@brief Constantly poll for new command or response data
*/
/**************************************************************************/
void loop(void)
{
if(digitalRead(button1) == 0)
{
delay(500);
ble.print("AT+BleHidControlKey=");
ble.println("PLAYPAUSE");
if( ble.waitForOK() )
{
Serial.println( F("OK!") );
}else
{
Serial.println( F("FAILED!") );
//Failed, probably pairing is not complete yet
Serial.println( F("Please make sure Bluefruit is paired and try again") );
}
}
if(digitalRead(button2) == 0)
{
delay(500);
ble.print("AT+BleHidControlKey=");
ble.println("HOME");
if( ble.waitForOK() )
{
Serial.println( F("OK!") );
}else
{
Serial.println( F("FAILED!") );
//Failed, probably pairing is not complete yet
Serial.println( F("Please make sure Bluefruit is paired and try again") );
}
}
if(digitalRead(button3) == 0)
{
delay(500);
ble.print("AT+BleHidControlKey=");
ble.println("VOLUME+");
if( ble.waitForOK() )
{
Serial.println( F("OK!") );
}else
{
Serial.println( F("FAILED!") );
//Failed, probably pairing is not complete yet
Serial.println( F("Please make sure Bluefruit is paired and try again") );
}
}
if(digitalRead(button4) == 0)
{
delay(500);
ble.print("AT+BleHidControlKey=");
ble.println("VOLUME-");
if( ble.waitForOK() )
{
Serial.println( F("OK!") );
}else
{
Serial.println( F("FAILED!") );
//Failed, probably pairing is not complete yet
Serial.println( F("Please make sure Bluefruit is paired and try again") );
}
}
}
Code Explanation
To start, a declaration of the buttons used is defined as:
// define buttons
#define button1 A3
#define button2 A4
#define button3 A0
#define button4 A1
Next, these keys are assigned as digital inputs with pull-ups:
// prepare button inputs
pinMode(button1, INPUT_PULLUP);
pinMode(button2, INPUT_PULLUP);
pinMode(button3, INPUT_PULLUP);
pinMode(button4, INPUT_PULLUP);
The next pieces of code are the usual setup processes to prepare the 32u4 and the Bluetooth module of your Bluefruit LE. You can find info on this in our previous blog.
Of particular interest here is the statement to enable the BLE-HID service:
/* Enable HID Service */
//Serial.println(F("Enable HID Services (including Control Key): "));
if (! ble.sendCommandCheckOK(F( "AT+BLEHIDEN=On" ))) {
error(F("Failed to enable HID (firmware >=0.6.6?)"));
}
Next, the loop code is given as:
void loop(void)
{
if(digitalRead(button1) == 0)
{
delay(500);
ble.print("AT+BleHidControlKey=");
ble.println("PLAYPAUSE");
if( ble.waitForOK() )
{
Serial.println( F("OK!") );
}else
{
Serial.println( F("FAILED!") );
//Failed, probably pairing is not complete yet
Serial.println( F("Please make sure Bluefruit is paired and try again") );
}
}
if(digitalRead(button2) == 0)
{
delay(500);
ble.print("AT+BleHidControlKey=");
ble.println("HOME");
if( ble.waitForOK() )
{
Serial.println( F("OK!") );
}else
{
Serial.println( F("FAILED!") );
//Failed, probably pairing is not complete yet
Serial.println( F("Please make sure Bluefruit is paired and try again") );
}
}
if(digitalRead(button3) == 0)
{
delay(500);
ble.print("AT+BleHidControlKey=");
ble.println("VOLUME+");
if( ble.waitForOK() )
{
Serial.println( F("OK!") );
}else
{
Serial.println( F("FAILED!") );
//Failed, probably pairing is not complete yet
Serial.println( F("Please make sure Bluefruit is paired and try again") );
}
}
if(digitalRead(button4) == 0)
{
delay(500);
ble.print("AT+BleHidControlKey=");
ble.println("VOLUME-");
if( ble.waitForOK() )
{
Serial.println( F("OK!") );
}else
{
Serial.println( F("FAILED!") );
//Failed, probably pairing is not complete yet
Serial.println( F("Please make sure Bluefruit is paired and try again") );
}
}
}
Each button is checked for a press and then debounced with a 500ms delay. Every time a button is pressed, the corresponding BLE AT HID Control Key command is sent to your phone’s Bluetooth module. A failure notice is displayed on the serial port if a “wait for OK check” is not received.
Below is a video of the code in action.
How to Send MIDI Control Change Messages using the 32u4 Feather Bluefruit LE
Have you tried to send MIDI messages from your Feather? Are controller change messages a challenge for you to accomplish? Read the rest of the article to find out.
Introduction
The previous blog talked about MIDI using the 32u4 Feather Bluefruit LE in general. This Feather is very useful, especially for simple MIDI Bluetooth Low Energy projects. The last example showed you how note messages can be sent through this device using the Adafruit BLE and BLE MIDI libraries. Now, this article focuses on how to send MIDI control change messages.
What are Control Change Messages in MIDI
A MIDI control message can enhance your musical output by controlling your instruments through various control elements such as knobs, sliders, wheels, pedals, and the like. Control messages have the form:
Status | Data Byte1 | Data Byte2 |
0xBX | Controller Number | Controller Value |
Where:
Status – Indicates the Controller Change type and Channel destination. B signifies a message of Controller Change type while X is the MIDI Channel number.
Controller Number – is a number ranging from 0 – 127 indicating the Controller type. Common Controller types include:
1 – Modulation Wheel
2 – Breath Controller
4 – Foot Controller
7 – Channel Volume
64 – Sustain Pedal On/Off
67 – Soft Pedal On/Off
Controller Value – Controller values usually range from 0 – 127 and this indicates the current position of your knobs, wheels, sliders, etc. Note that there are controllers which are “switch types”. They get an OFF value if the Controller value falls in the range of 0-63 while they get an ON value if the range is 64 – 127. There are also control values that require more granularity so they need multiple data bytes to function.
How to Use Controller Change Messages in your 32u4 BlueFruit LE Feather
It’s almost like doing simple Note On and Off messages based on the previous blog. However, there are more varied functions with each type of controller you use and you may have to experiment with this according to your synthesizer. For example, you’ll find wind instruments use the breath controller efficiently. The sustain pedal can be very useful for pianos or keyboards. The sample code in the next part demonstrates 2 potentiometers used as controller change elements.
Example Code
#include
#include
#include "Adafruit_BLE.h"
#include "Adafruit_BluefruitLE_SPI.h"
#include "Adafruit_BluefruitLE_UART.h"
#include "Adafruit_BLEMIDI.h"
#if SOFTWARE_SERIAL_AVAILABLE
#include
#endif
#include "BluefruitConfig.h"
#define FACTORYRESET_ENABLE 1
#define MINIMUM_FIRMWARE_VERSION "0.7.0"
// define buttons
#define button1 A3
#define button2 A4
#define control_change1 A0
#define control_change2 A1
// define control change functions
#define modulation_wheel 1
#define channel_volume 7
#define pan_controller 10
#define reverb 91
// This app was tested on iOS with the following apps:
//
// https://itunes.apple.com/us/app/midimittr/id925495245?mt=8
// https://itunes.apple.com/us/app/igrand-piano-free-for-ipad/id562914032?mt=8
//
// To test:
// - Run this sketch and open the Serial Monitor
// - Open the iGrand Piano Free app
// - Open the midimittr app on your phone and under Clients select "Adafruit Bluefruit LE"
// - When you see the 'Connected' label switch to the Routing panel
// - Set the Destination to 'iGrand Piano'
// - Switch to the iGrand Piano Free app and you should see notes playing one by one
// Create the bluefruit object, either software serial...uncomment these lines
/*
SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN);
Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN,
BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN);
*/
/* ...or hardware serial, which does not need the RTS/CTS pins. Uncomment this line */
// Adafruit_BluefruitLE_UART ble(BLUEFRUIT_HWSERIAL_NAME, BLUEFRUIT_UART_MODE_PIN);
/* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */
Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);
/* ...software SPI, using SCK/MOSI/MISO user-defined SPI pins and then user selected CS/IRQ/RST */
//Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_SCK, BLUEFRUIT_SPI_MISO,
// BLUEFRUIT_SPI_MOSI, BLUEFRUIT_SPI_CS,
// BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);
Adafruit_BLEMIDI midi(ble);
bool isConnected = false;
int current_note1 = 60;
int current_note2 = 72;
int current_control1, last_control1;
int current_control2, last_control2;
// A small helper
void error(const __FlashStringHelper*err) {
Serial.println(err);
while (1);
}
// callback
void connected(void)
{
isConnected = true;
Serial.println(F(" CONNECTED!"));
delay(1000);
}
void disconnected(void)
{
Serial.println("disconnected");
isConnected = false;
}
void BleMidiRX(uint16_t timestamp, uint8_t status, uint8_t byte1, uint8_t byte2)
{
Serial.print("[MIDI ");
Serial.print(timestamp);
Serial.print(" ] ");
Serial.print(status, HEX); Serial.print(" ");
Serial.print(byte1 , HEX); Serial.print(" ");
Serial.print(byte2 , HEX); Serial.print(" ");
Serial.println();
}
void setup(void)
{
while (!Serial); // required for Flora & Micro
delay(500);
// prepare button inputs
pinMode(button1, INPUT_PULLUP);
pinMode(button2, INPUT_PULLUP);
Serial.begin(115200);
Serial.println(F("Adafruit Bluefruit MIDI Example"));
Serial.println(F("---------------------------------------"));
/* Initialise the module */
Serial.print(F("Initialising the Bluefruit LE module: "));
if ( !ble.begin(VERBOSE_MODE) )
{
error(F("Couldn't find Bluefruit, make sure it's in CoMmanD mode & check wiring?"));
}
Serial.println( F("OK!") );
if ( FACTORYRESET_ENABLE )
{
/* Perform a factory reset to make sure everything is in a known state */
Serial.println(F("Performing a factory reset: "));
if ( ! ble.factoryReset() ) {
error(F("Couldn't factory reset"));
}
}
//ble.sendCommandCheckOK(F("AT+uartflow=off"));
ble.echo(false);
Serial.println("Requesting Bluefruit info:");
/* Print Bluefruit information */
ble.info();
/* Set BLE callbacks */
ble.setConnectCallback(connected);
ble.setDisconnectCallback(disconnected);
// Set MIDI RX callback
midi.setRxCallback(BleMidiRX);
Serial.println(F("Enable MIDI: "));
if ( ! midi.begin(true) )
{
error(F("Could not enable MIDI"));
}
ble.verbose(false);
Serial.print(F("Waiting for a connection..."));
}
void loop(void)
{
// interval for each scanning ~ 500ms (non blocking)
ble.update(500);
// bail if not connected
if (! isConnected)
return;
// Get analog control readings
current_control1 = (analogRead(control_change1) >> 3);
current_control2 = (analogRead(control_change2) >> 3);
if(abs(current_control1-last_control1) > 4)
{
Serial.println(current_control1);
midi.send(0xB0, modulation_wheel, current_control1);
last_control1 = current_control1;
}
if(abs(current_control2-last_control2) > 4)
{
Serial.println(current_control2);
midi.send(0xB0, channel_volume, current_control2);
last_control2 = current_control2;
}
if(digitalRead(button1) == 0)
{
// send note on
midi.send(0x90, current_note1, 0x64);
delay(500);
// send note off
midi.send(0x80, current_note1, 0x64);
delay(500);
}
if(digitalRead(button2) == 0)
{
// send note on
midi.send(0x90, current_note2, 0x64);
delay(500);
// send note off
midi.send(0x80, current_note2, 0x64);
delay(500);
}
}
Here is the whole code.
// define buttons
#define button1 A3
#define button2 A4
#define control_change1 A0
#define control_change2 A1
// define control change functions
#define modulation_wheel 1
#define channel_volume 7
#define pan_controller 10
#define reverb 91
Here are the defines used
int current_note1 = 60;
int current_note2 = 72;
int current_control1, last_control1;
int current_control2, last_control2;
Here are some of the additional declared variables.
Current_note1 and 2 are constant note values that will be sent as Note ON and OF messages. You’ll be able to apply controller change values on these notes and hear distinct changes in the way they sound.
Current_control1 and 2 hold the current controller values that change while you turn the potentiometer. last _control1 and 2 hold the previous controller values so that you’ll know if there was a specific change that happened. When the values change significantly, a controller change message will be sent. This is illustrated in the code segment below:
// Get analog control readings
current_control1 = (analogRead(control_change1) >> 3);
current_control2 = (analogRead(control_change2) >> 3);
if(abs(current_control1-last_control1) > 4)
{
Serial.println(current_control1);
midi.send(0xB0, modulation_wheel, current_control1);
last_control1 = current_control1;
}
if(abs(current_control2-last_control2) > 4)
{
Serial.println(current_control2);
midi.send(0xB0, channel_volume, current_control2);
last_control2 = current_control2;
}
The current_control1 value changes the modulation wheel while current_control2 changes the channel volume.
The note messages are simply relayed when you press the 2 digital buttons as seen below:
if(digitalRead(button1) == 0)
{
// send note on
midi.send(0x90, current_note1, 0x64);
delay(500);
// send note off
midi.send(0x80, current_note1, 0x64);
delay(500);
}
if(digitalRead(button2) == 0)
{
// send note on
midi.send(0x90, current_note2, 0x64);
delay(500);
// send note off
midi.send(0x80, current_note2, 0x64);
delay(500);
}
Upload the source code to your Bluefruit Feather.
Next, download the midimittr and the Perfect Piano app from the Appstrore to your iPhone. On midimittr, go to Device and connect to Adafruit Bluefruit LE. After that, open Perfect Piano. You should now be able to play your Feather as a musical instrument.
Make a MIDI Controller with Adafruit 32u4 Bluefruit LE
Would you like to know how to use the Adafruit 32u4 Bluefruit LE as a MIDI Controller? Read this article to find out.
Introduction
MIDI stands for Musical Instrument Digital Interface. It’s a protocol designed to help different devices that produce or accept musical tones in electrical form communicate with each other. It was established in the 1980s. The two persons behind it pushing for standardization were Ikutaro Kakehashi (Roland) and Dave Smith (Sequential Circuits).
MIDI made it possible for musicians to interface with electronic instruments such as controllers, synthesizers, and computers (as digital audio workstations) more easily.
MIDI Controllers – MIDI devices that can generate MIDI notes or messages.
MIDI Synthesizers – MIDI devices that can generate actual sounds.
Through these devices, varied connections can be made, even daisy-chaining them from one another. MIDI generates notes and can also be programmed to output their specific timings and tones. Through this method, MIDI file sizes can actually be smaller compared to actual audio file sizes.
MIDI in microcontrollers
MIDI is perfect for microcontrollers because its tones and timings can be programmed. With this, you can program them as MIDI controllers. After that, you’ll need a way to send or receive MIDI messages to and from your MIDI-capable devices. A common setup is to make a MIDI controller out of your microcontroller and then transfer MIDI messages to a synthesizer or a digital audio workstation (such as a PC). With this, here are the different ways that you can connect MIDI-capable devices to one another.
Through a MIDI Cable
This is the classical way of communication through MIDI. This is composed of a DIN-5 connector and cable. MIDI messages are transferred through this cable without using any audio signal. Through this, concise communication can be made, eliminating the nature of analog noise.
Through MIDI over UART
MIDI messages can travel over UART lines. This was the easier route for microcontrollers before as many did not have USB controllers back then. The UART protocol has been here for a long time now and is widely accepted.
Through USB MIDI
With the advent of putting USB controllers on microcontrollers, USB MIDI devices are on the rise. It’s easy to set up USB MIDI as many of them are plug-and-play. Additionally, you can easily hook up USB MIDI devices to a PC and use different kinds of music software with them.
Through BLE MIDI
BLE MIDI is a perfect setup for mobile gadgets that has MIDI features such as tablets or smartphones. With this, MIDI messages are transferred through a Bluetooth connection. This requires a Bluetooth peripheral installed on both the source and destination side. Fortunately, nowadays, it’s easy to set up and operate Bluetooth over MIDI thanks to its serial nature of communication using AT-style commands.
Making your First BLE MIDI Controller using a Feather Microcontroller
Probably one of the easiest ways to set up a MIDI controller is through Adafruiit Feather boards. There are several boards available for this, however, this article will focus on the 32u4 BlueFruit LE board. This Feather board has just the right specification to create simple BLE MIDI projects. Before you begin, you can browse through some introductory setup procedures for the 32u4 Bluefruit LE found in this article.
A Simple BLE MIDI example
You can build a BLE MIDI keyboard easily by using the midi project as a reference from the Adafruit BluefruitLE nRF51 examples directory.
Make Sure to Update your 32u4 Bluefruit LE’s nRF51288 to the latest Firmware Version
Download the latest Bluefruit Connect app from the Appstore. After turning on your Feather, run the app. Connect to your Feather that’s usually named Adafruit Bluefruit LE. If your Feather does not have the latest Bluetooth nRF51288 firmware, now is the time to update it. This will ensure that the example projects will run smoothly on your board.
Some Code Explanation
Change the SPI Hardware Settings of the BluefruitConfig.h config file
Change the hardware SPI settings to be compatible with your 32u4 BluiFruit LE as seen below. The BLUEFRUIT_SPI_RST pin should be changed accordingly.
BLE and MIDI Setup
Here the ble object is instantiated as an Adafruit_BluefruitLE_SPI type while the midi object an Adafruit_BLEMIDI type.
BLE MIDI receive function
A BleMidiRx() function is declared to be used as callback when MIDI IN Messages arrive. It simply displays the notes it received via Bluetooth.
BLE and MIDI Initialization
The usual BLE initialization code is written here.
Of particular interest here is how to begin the midi object through the midi.begin() statement
Sending MIDI Note Messages
Here, the actual MIDI messages are sent through the midi.send() command. The parameters include a status (examples of such are Note ON – 0x90, Note OFF – 0x80, or a Control Change Message – 0xB0 and others) and several data bytes. For a Note ON or OFF, the first data byte is the actual note itself (from 0 to 127), while the second data byte is the velocity or how fast you pressed the key (from 0 to 127). For a Control Change, the first data byte is the controller type (0-127) and then followed by the controller value (0-127). You can use the control change to control functions in a synthesizer.
The current note is simply incremented one by one inside the loop. As the midi notes are sent, a receive function BLEMidiRx() displays the notes serially. Open the serial monitor to view this.
Download the necessary mobile apps for the BLE MIDI function
The midimittr app (MIDI over Bluetooth) and the Grand piano app (synthesizer) in the Appstore will work hand in hand to hear the MIDI messages coming from your Bluefruit Feather. Midimittr has the capability to route the MIDI messages to another application such as the iGrand Piano which turns the messages into actual sounds.
First, connect your Adafruit Bluefruit LE to the midimittr app. Next, Open the iGrand Piano. Now go back to midimittr and make sure that the sources and destinations are met accordingly. You should hear the piano sounds afterward.
The Basics of Electronics: An Introduction for Beginners
Electronics is a complex and fascinating field that deals with the behavior and control of electrons. It has a wide range of applications, from the devices we use in our daily lives to the complex systems that drive modern technology. If you’re new to electronics, it can be overwhelming to understand the basics of this field. In this article, we’ll provide an in-depth introduction to the fundamentals of electronics and the principles that govern how it works.
What is Electronics?
Electronics is a field of science that deals with the behavior and control of electrons. It involves the study of materials and devices that use electrons to control or transform electrical energy. The goal of electronics is to create circuits and devices that perform useful functions.
Electrical Charge and Current
Electrons are negatively charged particles that orbit around the nucleus of an atom. They have a negative charge, and protons have a positive charge. When there is a difference in electrical charge between two points, there is an electrical potential difference or voltage. When electrons move through a conductor, such as a wire, it creates an electric current. The unit of measurement for current is the ampere (A).
Voltage and Resistance
Voltage is a measure of the difference in electrical potential between two points. It is measured in volts (V). Resistance is the ability of a material or component to resist the flow of electrical current. It is measured in ohms (Ω). Ohm’s law states that the current through a conductor between two points is directly proportional to the voltage across the two points, and inversely proportional to the resistance between them.
Resistors
A resistor is an electrical component that resists the flow of current through a circuit. It is used to control the amount of current that flows through a circuit. Resistors are measured in ohms (Ω), and the higher the resistance, the lower the current. Resistors come in various sizes and shapes, and their values are marked with color codes.
Capacitors
A capacitor is an electrical component that stores electrical energy in an electric field. It consists of two conductive plates separated by an insulating material. When a voltage is applied to the plates, it creates an electric field that stores electrical energy. Capacitors are used in filters, timing circuits, and power supplies. Capacitance is the ability of a capacitor to store charge, and it is measured in farads (F).
Diodes
A diode is an electrical component that allows current to flow in only one direction. It has a positive and a negative terminal, and current flows from the positive to the negative terminal. Diodes are used in rectifiers, voltage regulators, and signal processing. The most common type of diode is the semiconductor diode.
Transistors
A transistor is an electrical component that can amplify or switch electronic signals. It is made up of three layers of material, and it has three terminals: the emitter, base, and collector. Transistors are used in amplifiers, oscillators, and digital circuits. There are two main types of transistors: bipolar junction transistors (BJTs) and field-effect transistors (FETs).
Integrated Circuits
An integrated circuit is a small electronic device that contains many components, such as transistors, resistors, and capacitors, on a single chip. It can perform many different functions, such as amplification, switching, and signal processing. Integrated circuits are used in computers, mobile phones, and other electronic devices. There are two main types of integrated circuits: analog and digital.
Conclusion
This article has provided an in-depth introduction to the fundamentals of electronics, including electrical charge and current, voltage and resistance, resistors, capacitors, diodes, transistors, and integrated circuits. Understanding these basic principles is essential to anyone interested in learning about electronics. By mastering these concepts, you can begin to build more complex circuits and devices. Remember, practice makes perfect, so don’t be afraid to experiment and try new things in your electronics projects.