By on March 16, 2020
Pin It


We build a lamp to set the desired colour via Bluetooth using a special App.  The project is based on Mercury System, created for the development of connectivity and IoT applications.


The lighting sector, like many other so to speak “historical” sectors, is experiencing, in recent years, increasing penetration by electronics and connectivity. If once it was enough the classic filament bulb, extremely inefficient but pleasing to the eye, today we are increasingly looking for efficient solutions, able to save money and make life more comfortable, to the point that now the term “Smart Lighting” is widely used to indicate the extension of the classic sector towards intelligent and connected systems. One of the companies pioneering in this field is certainly Philips, which offers absolutely cutting-edge connected Smart Lighting solutions, such as the HUE connected lighting system (Fig. 1).


Fig. 1


While remaining in limited space, in this article we want to propose the realization of a similar object, which can find a place and a function in our living room or in our bedroom: a connected moodlamp, controllable via Bluetooth. By moodlamp we mean a lamp able to illuminate with various colours, which is able to create atmospheric lighting and to give some colour to the environment that it will illuminate (Fig. 2). The presence of intelligence onboard and connectivity will allow us to control it comfortably through our smartphone and also to create some special lighting effects.


Fig. 2


What we want to realize is the simple concept of Fig. 3. We will use a normal commercial lamp (the model is relatively indifferent, for our experiments we used an IKEA HOLMO lamp) that we will modify by inserting inside it an electronic board made with some Mercury modules and coloured LED strips. The Mercury system inserted inside the lamp will be equipped with a Bluetooth modem (we will use the MB310 modem card), so that it will be possible to control the lighting of the strips inserted inside the lamp, and consequently the colour of the lighting, through a common smartphone. Clearly it will also be necessary to develop a special app and a simple communication protocol that allows the control of Moodlamp; then we will deal with the description of these details. In addition to direct control, we will also provide the possibility to activate ignition sequences.


Fig. 3


Setup HW

As mentioned in the previous paragraph we will use the Mercury system for the realization of our moodlamp. The Mercury modules that we will need for the realization of the moodlamp are those summarized below.

BB110 – Base Board Model A: this card will be the logical unit of our system and will run the main application that will intercept the messages sent on the BT channel and control the LED strip on and off.

MB310 – Modem Board BT: this is the card that will provide the system with the BT connectivity, and therefore will allow the card to communicate with the control app installed on our smartphone.

SB140 – Slave Board HSD: this is the slave board that allows direct control on the LED strip.

PB110 – Power Board 12V 1,5A: this is the card we will use to power the system. The PB110 can be powered at 12V (we can, therefore, use a common wall adapter that provides that voltage level in output) and is able to provide power at 5V and 12V, for a total of 1.5A. The 12V output, in this case, is necessary to turn on the LED strip.

EB111 – Expansion Quad: Finally, to connect the various Mercury modules together, we will use a 4-slot expansion board, the EB111.


Fig. 4 shows the block diagram of the system hardware. The assembly of the system is very simple, just start with the EB111 and mount the BB110, PB110 and SB140 on the various slots it is equipped with. At this point, you can mount the MB310 modem board on the modem connector of the BB110, and the assembly is completed.


Fig. 4


The last operation to be performed is to set the SB140 slave board address to 1. Fig. 5 shows a picture of the complete assembly system.


Fig. 5


We can define this set, which we made by connecting the various Mercury modules described above, as a Moodlamp control board.

For the development of the application on the BB110 we will use the Mercury System Framework, in order to minimize the effort in the development of drivers and communication stacks and focus mainly on application logic. The development of the smartphone app can be done with various development environments, we decided to use MIT AppInventor, a completely online development tool that uses a graphical programming language very similar to Scratch for the development of Android applications.


Protocol of communication

Before moving on to a detailed description of the SW, we dedicate a few lines to the description of the communication protocol used to control the embedded part from our smartphone. As mentioned in the previous sections, for the communication we will use a BT channel, using the Mercury MB310 modem. This card encapsulates inside it a BT HC-05 module, which implements the BT SPP (Serial Port Profile). The use of this profile simplifies a lot the management of the communication because on the side of the BB110 it’s about managing simple ASCII strings.

Although the complexity is reduced, it is still necessary to define a simple communication protocol to allow simple management of the LED strip. Our Moodlamp will manage the switching on of three LED strips, one red, one green and one blue, through three channels of the SB140 (High Side Driver), so we will have to provide the commands at the protocol level for the switching on and off of each of these strips. We also want to provide a command for the setting of power on sequences that allow us to create lighting effects.

To make it as simple as possible we decided to implement a simple ASCII protocol based on groups of functionalities identified by a letter, followed by a control character (‘:’). In addition to the function group and the control character, there are two additional bytes to set the desired function. Table 1 summarizes the functionalities implemented for each group.

The protocol is deliberately simple and expandable so that it is possible for the user to further expand the moodlamp functionality, for example by adding additional coloured strips or new power-up sequences.

Table 1


Sw implementation

Let’s now move on to the description of the SW implementation of the embedded part of our project, i.e. the one running on the Base Board BB110, starting from the requirements definition. In short, we want our moodlamp to be able to:

  • initialize the MB310 by naming the BT module with the Mercury Moodlamp string (this will allow us to easily associate the moodlamp to our smartphone);
  • upon receiving a message on the BT channel identified with the functional group “C”, activate or deactivate the required strip;
  • upon receiving a message on the BT channel identified with the functional group “S”, activate or deactivate the set sequence. In this article, we present only a simple sequence that activates the LED strips cyclically one after the other, with a settable interval, but it is possible to expand this functionality with further sequences implemented ad hoc.


As mentioned above, for the realization of this project we need the latest version of the Mercury Software Framework (MSF) available, v1.1.0, which you can download from the open electronics website or, alternatively, from this web address, which also contains all previous versions. We also suggest updating the FW of the slaves, as this version is not compatible with the FW of slave nodes prior to version 1.2.0. To update the nodes, please refer to the MS_SlaveFwUpgradePackage manual, contained in the Documentation section of the MSF installation folder.

Once you have downloaded and correctly installed the MSF you can proceed to create a new project, which you can call for example “BtMoodlamp”.


System Configuration

Once created and renamed the new project you should get a screenshot of the MPLab X project manager similar to the one shown in Fig. 6.


Fig. 6


At this point we can go to the system configuration, updating the sys_cfg.h files. In our case, the only setting we are interested in changing is the one related to the modem, since we want to enable Bluetooth support, as shown in Fig. 7.


Fig. 7


BT module initialization

Now that we have completed the configuration of our project we can move on to the implementation of the first functions, starting with the initialization of the BT module. What we want to do is to assign a name to the module, so that it can be easily associated also in presence of other BT devices, and to do this we will need to temporarily set the communication mode “AT”, which allows the module to receive commands in AT mode, which also intervenes on different configuration parameters (such as the name to be assigned to the module, but also several others, such as the baud rate, the role of the device and many others). After performing this configuration we intend to reset the COM communication mode, i.e. the transparent mode (what is sent or received by the module corresponds to what is sent and received on the BT channel).

The function that implements what described is the BtInit function, represented in Listing 1, which performs the three operations described above in succession.

Listing 1

void BtInit(void)
static BtInitStsType BtInitState = BT_IN_SET_AT_MODE;
static BtInitStsType BtInitlNextState = BT_IN_SET_AT_MODE;
static SwTimerType BtSwTimer = SW_TIMER_INIT_EN;
switch (BtInitState)
/* Set AT mode */
/* Switch state with delay */
BtInitState = BT_IN_WAIT;
BtInitlNextState = BT_IN_UPDATE_MNAME;
/* Update Module name */
MdmBt_SetModuleName(“Mercury MoodLamp”);
/* Switch state with delay */
BtInitState = BT_IN_WAIT;
BtInitlNextState = BT_IN_SET_COM_MODE;
/* Set COM mode */
/* Update status variable */
BtSts = READY;
/* Switch state with delay */
BtInitState = BT_IN_WAIT;
BtInitlNextState = BT_IN_END;
case BT_IN_END:
case BT_IN_WAIT:
/* Check if the timer expired */
if (OsTmr_GetTimerStatus(&BtSwTimer) == SwTimerExpired)
/* Switch state */
BtInitState = BtInitlNextState;
? Fig. 8
API MdmBt_


Led strip control

Now that our module is correctly initialized we can switch to the management of the commands coming from the BT channel. For the reception of the data, we have a special API of the framework that allows us to verify if a message has been received and if so, to save its content in a reception buffer.


Fig. 8


The API is called MdmBt_ReceiveBtMsg and Fig. 8 shows the relative descriptive table extracted from the User Manual of the framework (MS_FrameworkUserManual). Note that this API, being triggered by a data reception event, is completely asynchronous and non-blocking, so it can be called comfortably in polling on our application task, without being blocking. Based on this API, we have implemented the MoodlampBt function, whose block diagram is shown in Fig. 9.


Fig. 9


As you can see from the block diagram, the function continuously checks if a message has been received on the BT channel, using the MdmBt_ReceiveBtMsg API. If so, the reception buffer is analyzed and the functional groups are managed. Listing 2 shows the implementation of the function: once determined if the message has been received, the content of the CmdBuffer reception buffer is checked; if the content of the first two bytes (identified by the GROUP_FIELD and CTR_FIELD indices) is equal to “C:”, the function switches to the direct management of the strips, otherwise if the content is equal to “S:”, the function switches to the management of the sequences.

Listing 2

void MoodlampBt (void)
UINT8 CmdBuffer[10];
UINT8 CmdLen;
if (MdmBt_ReceiveBtMsg(CmdBuffer,&CmdLen) == BtMsg_Received)
if ((CmdBuffer[GROUP_FIELD] == ‘C’) && (CmdBuffer[CTR_FIELD] == ‘:’))
if (CmdBuffer[CMD_FIELD] == ‘R’)
Hsd1Sts = (CmdBuffer[HSD_STS_FIELD] == ‘1’) ? STD_ON : STD_OFF;
else if (CmdBuffer[CMD_FIELD] == ‘G’)
Hsd2Sts = (CmdBuffer[HSD_STS_FIELD] == ‘1’) ? STD_ON : STD_OFF;
else if (CmdBuffer[CMD_FIELD] == ‘B’)
Hsd3Sts = (CmdBuffer[HSD_STS_FIELD] == ‘1’) ? STD_ON : STD_OFF;
else if ((CmdBuffer[GROUP_FIELD] == ‘S’) && (CmdBuffer[CTR_FIELD] == ‘:’))
MoodCyc = (CmdBuffer[SEQ_TYP_FIELD] == ‘1’) ? MoodCyc = STD_ON : MoodCyc = STD_OFF;
/* Set global variable */
HsdSts = Hsd1Sts | (Hsd2Sts << 1) | (Hsd3Sts << 2);
/* Update relay status */


To directly manage the strips, the SB140’s 0x50 command is used, which allows to directly set the status of the output channels through a byte, treated as a bit field (the first bit controls channel 1, the second-bit controls channel 2, etc.). For more details see the SB140 datasheet.

To send the correct message to the slave board, the command byte (HsdSts = Hsd1Sts | (Hsd2Sts << 1) | (Hsd3Sts << 2)) is built and then sent through the UpdateHsd function, whose code is reported in Listing 3. According to the composition of the command byte, we determine the connection of the strips to the HSD channels; in our example, the mapping is the following:

  • HSD CH1  Red
  • HSD CH2  Green
  • HSD CH3  Blue


But of course, you can change it, as you can also choose different colour strips according to your preferences.

Listing 3

void UpdateHsd (UINT8 Hsd, UINT8 SlaveAddr)
/* Prepare packet */
I2cTxBuffer[0] = SET_HSD_STS;
I2cTxBuffer[1] = Hsd;
/* Send I2C message */
I2cSlv_SendI2cMsg(I2cTxBuffer, SlaveAddr, sizeof(I2cTxBuffer));


For the implementation of the sequence instead, we use a second function, always invoked to the task, which implements a simple state machine. The BtMoodlamp function, in this case, is only concerned to intercept the command and set the global variable MoodCyc, which will be used to start or stop the sequence itself.


Automatic sequence

Let us now move on to the description of the state machine that implements the example sequence we have developed, whose block diagram is shown in Fig. 10. As mentioned before, the state machine execution is bound to the state of the global variable MoodCyc, which is set by a command sent on the BT channel; if the variable is set to STD_ON then the sequence is executed, otherwise not.


Fig. 10.


If executed, the state machine does nothing but pass through three states in sequence (BLUE_STATE, RED_STATE, GREEN_STATE), with a delay equal to ROUND_TRIP_DELAY_MS, which in our example is worth 250 ms. In each of the three states, the HSD channel connected to the corresponding colour strip is activated. Listing 4 shows the implementation of the machine in C code states. Finally, let’s not forget that the functions described above must still be invoked on our application task in order to run, as shown in Listing 5.

Listing 4

void MoodlampCyclic (void)
static UINT8 RoundCycState = BLUE_STATE;
static UINT8 NextState = BLUE_STATE;
static UINT16 Counter = 0;
if (MoodCyc == STD_TRUE)
switch (RoundCycState)
/* Set HSD */
HsdSts = STD_ON | (STD_OFF << 1) | (STD_OFF << 2);
/* Switch state */
RoundCycState = DELAY_STATE;
NextState = RED_STATE;
/* Set HSD */
HsdSts = STD_OFF | (STD_ON << 1) | (STD_OFF << 2);
/* Switch state */
RoundCycState = DELAY_STATE;
NextState = GREEN_STATE;
/* Set HSD */
HsdSts = STD_OFF | (STD_OFF << 1) | (STD_ON << 2);
/* Switch state */
RoundCycState = DELAY_STATE;
NextState = BLUE_STATE;
/* Increment counter */
/* Check for timeout */
if (Counter >= ROUND_TRIP_DELAY_MS)
/* Reset counter */
Counter = 0;
/* Switch state */
RoundCycState = NextState;


Clearly further sequences can be developed, it will be enough to develop a new state machine that implements the sequence itself and then expand the BtMoodlamp function to manage its activation.

Listing 5

void MyApp_Task (UINT8 Options)
switch (SystemState)
/* System Initialization Phase */
case InitializationState:
/* Make app init if necesary */
/* System Normal operation Phase */
case RunningState:
/* System Initializations */
/* If system is ready start the actual application */
if (BtSts == READY)
/* BT control */
/* Mood cyclic */
/* Default */


Control app

Finally, let’s spend a few words on the control app, made as anticipated with App Inventor. The app, of which you can see a screenshot in Fig. 11, allows you to connect the moodlamp to your smartphone and control the switching on and off of the various LED strips using 6 special buttons. You can also activate or deactivate the sequence using two additional buttons.


Fig. 11


Wiring and testing

Finally, we move on to the electrical connections inside the control board and between the control board and the LEDs. First, we set the jumpers correctly: there are two of them, one on PB110 and one on SB140, both named JP1. The jumper on the PB110 must be set to “Vbat”, so as to supply 5V to the system without the need to use the CN5 screw connector.

On the other hand, the jumper on the SB140 must be set to the “Ext” value, in order to connect +12V (Val) directly to the positive pole of the screw terminal block of the SB140 (the strips must be powered at 12V).

At this point it will be sufficient to make the following electrical connections:

  • The Val terminal of connector CN6 of PB110 must be connected to the Ext_Vdd terminal (terminal 1) of connector CN4 of SB140;
  • all negative terminals of the LED strips must be connected to the GND terminal (terminal 2) of connector CN4 of the SB140;
  • The positive terminal of the red LED strip must be connected to the HSD1_Out channel (terminal 3) of connector CN4 of the SB140;
  • The positive terminal of the green LED strip must be connected to the HSD2_Out channel (terminal 4) of connector CN4 of the SB140;
  • The positive terminal of the blue LED strip must be connected to the HSD3_Out channel (terminal 5) of connector CN4 of the SB140.


Fig. 12 shows a connection example with a single LED strip as an example.


Fig. 12


At this point, all that remains to be done is to place the control board inside the lamp you have chosen and power it through a 12V power supply (for the connection you can use the Jack terminal of the SB140). To test that everything works properly, install the control app, associate the module (password 1234), connect it and finally try to illuminate the room with your new moodlamp.



In this article, we have developed a very simple version of Moodlamp, but one that allows us to have a very technological and environmentally friendly furnishing accessory in which it is used. Clearly the project can be much improved, both by adding other strips (the modularity of the Mercury System would allow to add more SB140, to be connected to other LED strips), and also by developing further lighting sequences. Let’s leave it to interested readers to explore these further possibilities, which can make this object even more functional and interesting


From openstore

Mercury System

About francescof

Leave a Reply