Introduction: Arduino Youtube Remote Control for Sleeping (Leobot Electronics)

Arduino Youtube Remote

If you use Youtube to provide you with a movie or music to watch while to sleeping you surely would have been woken up by either a load advert or different volume levels when a new movie starts. Needless to say, this can be quite irritating.

So, my solution I prove to you here to build for yourself is an Arduino-based remote control to interact with Youtube at a distance. The remote is required to change my PC’s main sound volume, skip adverts on Youtube and skip videos on Youtube.

Also, included is an audio level sensor to determine how loud the speaker actually is, which in turn can be used to automatically lower the sound level upon detect loud interruptions such as an advert.

Lastly, I added a chart on the PC app to display the detected audio levels.

The solution can be better refined but for me it accomplishes the task.

Step 1: Components Needed

All these components are supplied by Leobot Electronics (https://leobot.net)

1) Arduino UNO R3

https://leobot.net/viewproduct.aspx?id=530

2) 4 CHANNEL REMOTE (315MHZ) + RECEIVER MODULE (315MHZ)

https://leobot.net/viewproduct.aspx?id=521

3) MICROPHONE VOICE & SOUND DETECTION SENSOR MODULE (KY-037)

https://leobot.net/viewproduct.aspx?id=217

Software

1) Visual Studio

https://visualstudio.microsoft.com/

2) Arduino IDE

https://www.arduino.cc/en/main/software

Step 2: Hardware Setup

1) Connect the 4-Channel receiver module to the Arduino.

4-Channel Receiver Pin->Arduino Uno Pin

GND->GND

5V->5V

D0->Digital 2

D1->Digital 3

D2->Digital 4

D3->Digital 5

2) Connect Microphone KY-037 module to the Arduino

Microphone KY-037 Pin->Arduino Uno Pin

GND->GND

+->3.3V

A0->Analog 3

Step 3: Arduino Code

Overview

The logic that the Arduino needs to follow is as follow:

A) Check if the receiver is signalling any pins.

B) Depending on which IO port the signal is received at is what command will be sent to the PC.

C) Once done with all remote-control actions, detect the audio level with the microphone and send it to the PC.

D) All commands send to the PC has a format of first having a character then a value (if a value is needed).

E) There are five commands sent from the Arduino to the PC

a. “u” - Volume Up

b. “d” - Volume Down

c. “s” - Skip Add

d. “v” - Skip Video

e. “a” - Audio Level detected followed by the value

The Arduino Code:

Download Arduino Code here:
https://leobot.net/audiousb.zip

int in1=2;

int in2=3;

int in3=4;

int in4=5;

void setup() {

Serial.begin(9600);

pinMode(A3,INPUT);

pinMode(in1,INPUT);

pinMode(in2,INPUT);

pinMode(in3,INPUT);

pinMode(in4,INPUT);

}

void loop() {

if(digitalRead(in1))

{

Serial.println("u");

delay(100);

}

if(digitalRead(in2))

{

Serial.println("d");

delay(100);

}

if(digitalRead(in3))

{

Serial.println("s");

delay(100);

}

if(digitalRead(in4))

{

Serial.println("v");

delay(100);

}

int readVal= analogRead(A3);

Serial.println(String("a")+ String( readVal));

delay(50);

}

Step 4: PC App Code (C#.NET)

The app will listen over the COM (USB) port and react depending on what command is received. The simplest way to turn the sound up and down on the PC is to use Interrop services to directly speak to the Windows OS. We also use the Interrop services to move the mouse to a specific position on the screen and click. In order to allow for different screens & view sizes, we allow the user to specify the position of the skip add and skip video buttons.

We use a standard .net chart to display any audio commands that we receive.

Windows Code:

Download full project here:

https://leobot.net/audioadjust.zip

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.Runtime.InteropServices;

using System.IO.Ports;

using System.Threading;

namespace AudioAdjust

{

public partial class Form1 : Form

{

[DllImport("User32.Dll")]

public static extern long SetCursorPos(int x, int y);

[DllImport("User32.Dll")]

public static extern bool ClientToScreen(IntPtr hWnd, ref POINT point);

[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]

public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);

//Mouse actions

private const int MOUSEEVENTF_LEFTDOWN = 0x02;

private const int MOUSEEVENTF_LEFTUP = 0x04;

private const int MOUSEEVENTF_RIGHTDOWN = 0x08;

private const int MOUSEEVENTF_RIGHTUP = 0x10;

[DllImport("user32.dll")]

static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);

Random aRand = new Random();

public int LastLevel = 0;

public int MaxLevel = 255;

static SerialPort _serialPort;

int adX = 1281;

int adY = 706;

int vidX = 250;

int vidY = 780;

bool enableAudioChange = false;

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

string[] names = System.IO.Ports.SerialPort.GetPortNames();

comboBoxPort.Items.AddRange(names);

comboBoxPort.SelectedIndex = 0;

}

int currentPoint = 0;

private void button1_Click(object sender, EventArgs e)

{

_serialPort = new SerialPort();

_serialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived);

_serialPort.PortName = comboBoxPort.SelectedItem.ToString();//Set your board COM

_serialPort.BaudRate = 9600;

if (_serialPort.IsOpen) _serialPort.Close();

else

{

_serialPort.Open();

}

// keybd_event((byte)Keys.VolumeDown, 0, 0, 0); // decrease volume

}

void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)

{

try

{

string fullval = _serialPort.ReadLine();

string com = fullval[0].ToString();

switch (com)

{

case "a":

{

{

//audio level

string val = fullval.Replace("a","");

int valInt = int.Parse(val);

AddData(valInt);

}

break;

}

case "u":

{

//audio up

keybd_event((byte)Keys.VolumeUp, 0, 0, 0); // decrease volume

break;

}

case "d":

{

//audio down

keybd_event((byte)Keys.VolumeDown, 0, 0, 0); // decrease volume

break;

}

case "s":

{

//skipAd

MoveCursorSkipAd();

Thread.Sleep(10);

DoMouseClick();

break;

}

case "v":

{

//skipAd

MoveCursorSkipVideo();

Thread.Sleep(10);

DoMouseClick();

break;

}

}

}

catch

{

}

//throw new NotImplementedException();

}

private void MoveCursorSkipAd()

{

Cursor.Position = new Point(1140, 725);

Cursor.Position = new Point(adX, adY);

}

private void MoveCursorSkipVideo()

{

Cursor.Position = new Point(1140, 725);

Cursor.Position = new Point(vidX, vidY);

}

public void DoMouseClick()

{

//Call the imported function with the cursor's current position

uint X = (uint)Cursor.Position.X;

uint Y = (uint)Cursor.Position.Y;

mouse_event(MOUSEEVENTF_LEFTDOWN, X, Y, 0, 0);

mouse_event(MOUSEEVENTF_LEFTUP, X, Y, 0, 0);

}

void AddData(int level)

{

if (enableAudioChange)

{

if (level >= MaxLevel)

{

keybd_event((byte)Keys.VolumeDown, 0, 0, 0); // decrease volume

keybd_event((byte)Keys.VolumeDown, 0, 0, 0); // decrease volume

keybd_event((byte)Keys.VolumeDown, 0, 0, 0); // decrease volume

}

else

{

if (level < MaxLevel - 0)

{

keybd_event((byte)Keys.VolumeUp, 0, 0, 0); // decrease volume

}

}

}

SetChart(level);

currentPoint++;

}

delegate void SetTextCallback(int val);

private void SetChart(int val)

{

// InvokeRequired required compares the thread ID of the

// calling thread to the thread ID of the creating thread.

// If these threads are different, it returns true.

if (this.chart1.InvokeRequired)

{

SetTextCallback d = new SetTextCallback(SetChart);

this.Invoke(d, new object[] { val });

}

else

{

chart1.Series[0].Points.AddXY(0, val);

if (currentPoint >= 10)

{

chart1.Series[0].Points.RemoveAt(0);

}

}

}

private void textBoxLevel_TextChanged(object sender, EventArgs e)

{

try

{

MaxLevel = int.Parse(textBoxLevel.Text);

}

catch

{

textBoxLevel.Text = MaxLevel + "";

}

}

private void buttonTestSkip_Click(object sender, EventArgs e)

{

MoveCursorSkipAd();

Thread.Sleep(10);

DoMouseClick();

}

private void textBoxXpos_TextChanged(object sender, EventArgs e)

{

try

{

adX = int.Parse(textBoxXpos.Text);

}

catch

{

textBoxXpos.Text = adX + "";

}

}

private void textBoxYpos_TextChanged(object sender, EventArgs e)

{

try

{

adY = int.Parse(textBoxYpos.Text);

}

catch

{

textBoxYpos.Text = adY + "";

}

}

private void buttonSkipVideo_Click(object sender, EventArgs e)

{

MoveCursorSkipVideo();

Thread.Sleep(10);

DoMouseClick();

}

private void textBoxXposVid_TextChanged(object sender, EventArgs e)

{

try

{

vidX = int.Parse(textBoxXposVid.Text);

}

catch

{

textBoxXposVid.Text = vidX + "";

}

}

private void textBoxYposVid_TextChanged(object sender, EventArgs e)

{

try

{

vidY = int.Parse(textBoxYposVid.Text);

}

catch

{

textBoxYposVid.Text = vidY + "";

}

}

private void checkBoxEnable_CheckedChanged(object sender, EventArgs e)

{

enableAudioChange = checkBoxEnable.Checked;

}

}

[StructLayout(LayoutKind.Sequential)]

public struct POINT

{

public int x;

public int y;

}

}