Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Control RGB LEDs Using Android and Arduino

DZone's Guide to

Control RGB LEDs Using Android and Arduino

This is an interesting topic because two ecosystems are mixed together and integrated. By picking a color from an app running on your Android smartphone, we will make an Arduino switch on a RGB LED of that same color.

· IoT Zone
Free Resource

Discover why Bluetooth mesh is the next evolution of IoT solutions. Download the mesh overview.

To make everything work there are several aspects to consider: first it is necessary to create an Android app so that we can select the color we want. Then, we need to send that data to Arduino. The data is built by the three colour values (Red, Green, Blue). On the Arduino side, we have to create a server that receives the three colours values and controls an RGB LED.

As a final result, we will get something like this:

Before digging into the project details, it is useful to have a project overview:
control rgb led connected to arduino using Android app
In a previous post we talked about how to turn on and off an LED connected to an Arduino using an Android app, now it is time to make things a little more complex.

To build this project, we need:

Android side:

  • Colour picker View
  • HTTP client that sends data

Arduino side:

  • HTTP server to get data
  • Simple JSON parser
  • RGB led handler

To control RGB led, the first step is creating an Android color picker UI so that the user can pick the color to turn on the RGB led. Let us start from the final Android UI result:

android color picker

To create this interface we used an interesting open source project called Color Picker. This component is very easy to use.

At the first step, we create the main layout based on the Android Floating Action Button:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:fitsSystemWindows="true"
 tools:context="com.survivingwithandroid.rgbcontroller.MainActivity"
 android:id="@+id/mainLyt">

 <android.support.design.widget.AppBarLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:theme="@style/AppTheme.AppBarOverlay">

 <android.support.v7.widget.Toolbar
 android:id="@+id/toolbar"
 android:layout_width="match_parent"
 android:layout_height="?attr/actionBarSize"
 android:background="?attr/colorPrimary"
 app:popupTheme="@style/AppTheme.PopupOverlay" />

 </android.support.design.widget.AppBarLayout>

 <include layout="@layout/content_main" />

 <android.support.design.widget.FloatingActionButton
 android:id="@+id/fab"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="bottom|end"
 android:layout_margin="@dimen/fab_margin"
 android:src="@android:drawable/ic_input_get" />

</android.support.design.widget.CoordinatorLayout>

Now when a user presses the FAB, the app will show the Color Picker dialogue:

@Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
 setSupportActionBar(toolbar);
 ......

 FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
 fab.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View view) {
 // Handle FAB click event
 }
 }
 }

It is time to show the Color picker dialog that will control the RGB LED in the onClick method:

ColorPickerDialogBuilder
 .with(MainActivity.this)
 .setTitle("Choose RGB color")
 .initialColor(Color.WHITE)
 .wheelType(ColorPickerView.WHEEL_TYPE.FLOWER)
 .lightnessSliderOnly()
 .density(12)
 .setOnColorSelectedListener(new OnColorSelectedListener() {
 @Override
 public void onColorSelected(int selectedColor) {
 // Nothing to do...
 }
 })
 .setPositiveButton("ok", new ColorPickerClickListener() {
 @Override
 public void onClick(DialogInterface dialog, int selectedColor, Integer[] allColors) {

 int r = (selectedColor >> 16) & 0xFF;
 int g = (selectedColor >> 8) & 0xFF;
 int b = (selectedColor >> 0) & 0xFF;
 Log.d("RGB", "R [" + r + "] - G [" + g + "] - B [" + b + "]");
 sendColor(r,g,b);
 }
 })
 .setNegativeButton("cancel", new DialogInterface.OnClickListener() {
 @Override
 public void onClick(DialogInterface dialog, int which) {
 }
 })
 .build()
 .show();

As you can see this component is very simple to use, when the user clicks OK, the app extracts the Red, Green, and Blue components and sends them to Arduino.

To send data to Arduino, we need to create a simple HTTP client that sends the Red, Green, and Blue components as a JSON string. Arduino will use this information to control the RGB LED. The Android HTTP client is very simple and it is based on OkHttp.

private void sendColor(int r, int g, int b) {
 Log.d("RGB", "Sending data to Arduino....");
 Request req = new Request.Builder()
 .url(URL)
 .post(RequestBody.create(JSON, createJSON(r,g,b)))
 .build();

 tv.setText("Sending data to Arduino...");

 client.newCall(req).enqueue(new Callback() {
 @Override
 public void onFailure(Call call, IOException e) {
 // Handle call failure
 }

 @Override
 public void onResponse(Call call, Response response) throws IOException {
 // OK Response...inform the user
 }
 });
 }

Where createJSON method is very simple:

private String createJSON(int r, int g, int b) {
 return "{\"color\": [" + r + "," + g + "," + b + "]}";
}

It returns the three color values.

The Android side is completed, as you can see with a few lines of code we created a nice Android app that will control an RGB LED connected to Arduino.

Now the Android client side is ready, it is time to build the Arduino side. The first step is creating the Arduino sketch. This tutorial uses a common anode RGB led, that means the Vcc is connected to the anode. If you use a common cathode led the cathode must be connected to the ground.
The Arduino sketch is shown below:
control rub led using arduino
The three LED pins are connected to Arduino PWM using a 300 ohm resistor. That’s all, the “hardware” part is ready to be used. If you want to test the Arduino to know if everything works correctly you can use this Arduino sketch.

In the diagram above, the ethernet shield is not shown to simplify the diagram. Of course, to connect Arduino to the Internet, it's necessary to have an ethernet shield or a Wi-Fi shield. This tutorial uses the ethernet shield.

Now that the “hardware” part is ready, Arduino has to accept the HTTP connection so that the Android client can send data (the RGB values). It is necessary to build, then, a simple HTTP server that parses the incoming requests and extracts the values.

In the setup method of the sketch, we initialize the Arduino PINs to control the RGB LED and the ethernet IP.

void setup() {
 // put your setup code here, to run once:
 Serial.begin(9600);

 // Pin mode
 pinMode(redPin, OUTPUT);
 pinMode(bluePin, OUTPUT);
 pinMode(greenPin, OUTPUT);
 Serial.print("Ready...");
 //
 Ethernet.begin(mac, ip); 
 server.begin(); 
 Serial.println("Begin...");
}

Now it is time to accept incoming requests and parse them:

void loop() {
 EthernetClient client = server.available(); // Is there a client (Our Android smartphone)

 if (client) {
 // Let's start reading
 boolean isLastLine = true;
 boolean isBody = false;
 header = "";
 reqData = "";
 int contentLen = 0;

 Serial.print("Client connected!");
 while (client.connected()) {
 if (client.available()) { 
 // Read data
 char c = client.read(); 

 // Serial.print(c);

 if (contentSize == contentLen) {
 Serial.println("Body ["+reqData+"]");
 // Extract the JSON string like [r,g,b]
 int pos1 = reqData.indexOf("[");
 int pos2 = reqData.lastIndexOf("]");

 // Parse the string looking for ,
 String colors = reqData.substring(pos1 + 1, pos2);
 Serial.println("Colors ["+colors+"]");
 int idx1 = colors.indexOf(',');
 int idx2 = colors.indexOf(',', idx1+1);
 int idx3 = colors.indexOf(',', idx2+1);
 String sRed = colors.substring(0, idx1);
 String sGreen = colors.substring(idx1 + 1, idx2);
 String sBlue = colors.substring(idx2 + 1, idx3);

 // Convert the Red, Green and Blue string values to int
 int red = sRed.toInt();
 int green = sGreen.toInt();
 int blue = sBlue.toInt();

 // Set the RGB led color according to the values sent by the Android client
 setColor(red, green,blue);

 // Create the response to client
 client.println("HTTP/1.1 200 OK");
 client.println("Content-Type: text/html");
 client.println("Connection: close");
 client.println();
 // send web page
 client.println("<!DOCTYPE html>");
 client.println("<html>");
 delay(1);
 break;
 }


 if (c == '\n' && isLastLine) {
 isBody = true;
 int pos = header.indexOf(CONTENT_LENGTH_TXT);
 String tmp = header.substring(pos, header.length());
 //Serial.println("Tmp ["+tmp+"]");
 int pos1 = tmp.indexOf("\r\n");
 String size = tmp.substring(CONTENT_LENGTH_TXT.length(), pos1);
 Serial.println("Size ["+size+"]");
 contentSize = size.toInt();

 }

 if (isBody) {
 reqData += c;
 contentLen++;
 }
 else {
 header += c; 
 }


 if (c == '\n' ) {
 isLastLine = true;
 }
 else if (c != '\r' ) {
 isLastLine = false;
 }

 }
 }

 // Close connection
 Serial.println("Stop..");
 client.stop();
 }
}

The source code seems to be complex but it is very simple if you look at it carefully. It is always an HTTP Arduino server.

The last part is setting the RGB LED color:

void setColor(int red, int green, int blue) {
 #ifdef COMMON_ANODE
 red = 255 - red;
 green = 255 - green;
 blue = 255 - blue;
 #endif


 analogWrite(redPin, red);
 analogWrite(bluePin, green);
 analogWrite(greenPin, blue);
}

Notice that if we use a common anode, we have to invert the values.

Source code available soon.

Take a deep dive into Bluetooth mesh. Read the tech overview and discover new IoT innovations.

Topics:
arduino ,android

Published at DZone with permission of Francesco Azzola, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}