Arduino Youtube Remote Control for Sleeping (Leobot Electronics)
by Leobot Electronics in Circuits > Arduino
387 Views, 0 Favorites, 0 Comments
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.
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
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
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);
}
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;
}
}