[Python / C] I made a device that wirelessly scrolls the screen of a PC remotely.

Synopsis

When practicing comics with friends, I display the lines on the computer in front of me and use it as a competition. If you display the characters in large size, you cannot see all the lines without scrolling. Therefore, I made a device that can scroll the screen of a personal computer up and down remotely.

System configuration

I thought of a system in which a PC scrolls when a switch attached to the controller at hand is pressed.

The configuration of the entire system is as follows.

キャプチャ.PNG

The details of the above system overview are shown below. (Because it is not only practical but also intended to be made as part of study, I chose it with the intention of using various devices.)

  1. Sender --Microcomputer: ATtiny2313 --Microcomputer write writer: AVRISP mkⅡ
  1. Receiving side --Microcomputer: Arduino Micro
  1. PC side

After that, I will not touch on it in this article, but I used the following as a communication debugging tool such as serial transmission and reception.

--USB / serial converter: MR-USBSIR-F --Terminal: TeraTerm

In addition, the wireless module by Bluetooth has the transmitting side (SBDBT) as the slave and the receiving side (rn42xvp-i / rm) as the master. The reason is that SBDBT is a slave by default, and a write writer for the microcomputer (PIC24FJ64GB004-I / PT) is required to change to the master. On the other hand, since the setting of rn42xvp-i / rm can be changed simply by sending a command from a terminal such as Arduino's serial monitor or TeraTerm, the setting of rn42xvp-i / rm on the sending side was changed and used as the master. (Details of setting will be described later)

I thought ... but rn42xvp-i / rm seemed to be the master by default. However, even if you think about it without it, you can easily change the settings and it is convenient, so I used rn42xvp-i / rm as the master.

Receiver wireless module: rn42xvp-i / rm settings

As mentioned above, the setting of the wireless module on the transmitting side cannot be changed without a pic writer, so rn42xvp-i / rm on the receiving side was used as the master. By changing the setting of rn42xvp-i / rm in advance by sending a command from the terminal, it is possible to connect Bluetooth modules.

The procedure is shown below. You can do it from the serial monitor of Arduino IDE or from TeraTerm. When executing from the serial monitor of Arduino, execute after writing the following.

change_bt_settings.c


#include <SoftwareSerial.h>

#define BT_RX 8
#define BT_TX 7
#define BPS 115200 // rn42xvp-i/rm default baud rate

SoftwareSerial btSerial(BT_RX, BT_TX); //Serial settings for interacting with Bluetooth

void setup()
{
  Serial.begin(BPS); // PC -Initialization of serial communication between Arduino
  btSerial.begin(BPS); // Arduino -Initialization of serial communication between Bluetooth
}

void loop()
{
  //Transmission process from Arduino to Bluetooth
  if (Serial.available())
  {
    btSerial.print(char(Serial.read()));
//    btSerial.write(Serial.read()); //Also OK here]
  }

  //Signal reception processing from Bluetooth
  if (btSerial.available())
  {
    Serial.print(char(btSerial.read()));
//    Serial.write(btSerial.read()); //Also OK here
  }
  delay(50);
}

In addition, I referred to the following article for implementation. ・ Http://workpiles.com/2014/04/rn42-bluetooth1/ ・ Htp: // Kosakai. Rld. Kokan. jp / R-42. html

The setting procedure is as follows.

number command new line response meaning
1 $$$ None CMD Command mode start
2 SA,0 Yes AOK Changed no authentication required for connection
3 SU,96 Yes AOK Change baud rate to 9600
4 R,1 Yes Reboot! Reboot the module (this will reflect the configuration changes)

What I made (hardware)

    1. Sender (ATtiny2313)

I thought about what to use as a base, but ordinary plastic plates and universal plates Since it is difficult to process, we used a 5 mm thick foamed styrene board that is relatively rigid and easy to process. The foamed styrene board was processed to an appropriate size, and a battery box and a board were attached.

image.png

image.png

  1. Receiving side (Arduino Micro)

The receiving side may be directly connected to a personal computer, so I created it on a breadboard.

image.png

source file

    1. Sender (ATtiny2313)

send_data_to_arduino.c


#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
 
#define OFF 0   //For switching
#define ON  1   //Same as above
#define READ  0 //For port register setting
#define WRITE 1 //Same as above
#define CNTD  0 //Used to measure the time the switch is held down
#define CNTU  1 //Same as above
#define KRTIME 100000 //Time to hold down the switch to be recognized as being pushed


void AVR_init(void)
{
	//Settings such as serial communication
	DDRD=(READ<<PD0)|(WRITE<<PD1)|(READ<<PD4)|(READ<<PD5)|(WRITE<<PD6);
}

void USART_init(void)
{
	unsigned int baud;
	baud=8000000/16/9600-1;          //Baud rate calculation(The calculation formula is the specification P.75 Listed at the bottom)
	UBRRH=(unsigned char)(baud>>8);  //Baud rate setting(Upper byte)
	UBRRL=(unsigned char)baud;       //Baud rate setting(Lower byte)
	UCSRC=(0<<USBS)|(3<<UCSZ0);      //Set the used bit length to 8 bits and the stop bit to 2 bits
	UCSRB=(1<<RXEN)|(1<<TXEN);       //Send / receive permission
}

void Utx(char *data) //Data transmission
{
	int i;
	
	//Terminated character "\Loop to "0"
	for(i=0; data[i]!='\0'; i++)
	{
		while(!(UCSRA & (1<<UDRE)) );
		UDR=data[i];
	}
}

void INT_init(void)
{
	//INT0 and 1(Pins 6 and 7)Allow interrupts
	GIMSK=0b11000000; //General interrupt enable register
	MCUCR=0b00001111; //Set external interrupt trigger on the up edge for both INT0 and 1
// 	SREG=0b10000000;  //Multiple interrupts disabled → Disabled by default
}

ISR(INT0_vect) //Pin 7 interrupt handler
{
	//Chattering measures
	_delay_ms(50);
	EIFR=ON<<INTF0;

	Utx("UP");
	Utx("_");  //Terminated character
}

ISR(INT1_vect) //Pin 6 interrupt handler
{
	//Chattering measures
	_delay_ms(50);
 	EIFR = ON<<INTF1;

	Utx("DOWN");
	Utx("_");  //Terminated character
}

unsigned char Urx(void) //Data reception
{
	while(!(UCSRA & (1<<RXC)) );
	return UDR;
}

int main(void)
{
	//Key repeat(Hold down the switch)Time measurement
	static unsigned long rptcnt[1] = {}; //Since int became 2 bytes, declare it as long
	
	AVR_init();
	USART_init();
	INT_init();
	sei(); //All interrupt enable instructions
		
	PORTD=ON<<PD6; //Always 5V output(For switching)

	for(;;)
	{
		//Correspondence processing to hold down the button
		if (bit_is_set(PIND, 4)) //When PD4 is 1 (pressing the button)
		{
			if (rptcnt[CNTD] > KRTIME) //Detects holding down
			{
				Utx("UP");
				Utx("_"); //Terminated character
				_delay_ms(100);
			}
			else //Add key repeat time
			{
				rptcnt[CNTD]++;
			}
		}
		else if (bit_is_set(PIND, 5)) //When PD5 is 1 (pressing the button)
		{			
			if (rptcnt[CNTU] > KRTIME) //Detects holding down
			{
				Utx("DOWN");
				Utx("_"); //Terminated character
				_delay_ms(100);
			}
			else //Add hold time
			{
				rptcnt[CNTU]++;
			}
		}
		else //Clear the holding time to zero
		{
			rptcnt[CNTD] = 0;
			rptcnt[CNTU] = 0;
			// memset(rptcnt, 0, sizeof(rptcnt)*10); //Do not use because it depends on the processing system
		}
	}
}
  1. Receiving side (Arduino Micro)

relay_data_to_PC.c


#include <SoftwareSerial.h>

#define BT_RX    8 // Arudino-Used for serial communication between Bluetooth
#define BT_TX    7 //Same as above
#define BAUD  9600 //Serial communication baud rate
#define OUT_5V   2 //Pin number
#define IN_5V    3 //Same as above
#define LED_OUT  4 //Same as above
#define BUFF_MAX 5 //Capacity of serial reception buffer (unit: characters)

// Arudino-Software serial settings between Bluetooth
SoftwareSerial btSerial(BT_RX, BT_TX);

void setup()
{
  Serial.begin(BAUD);
  btSerial.begin(BAUD);
  pinMode(OUT_5V, OUTPUT); //Used for switching
  pinMode(IN_5V,  INPUT);  //Same as above
}

void init_bt() //Connection with Bluetooth module
{
  btSerial.print("$$$"); //Transition to setting mode
  delay(1000);
  btSerial.print("C,00198600035E\n"); //Connect to other bluetooth modules
  delay(5000);
  btSerial.print("---\n"); //Exit command mode if connection fails (ignored on success)
}

void loop()
{
  char buff[BUFF_MAX]={'\0'};
  static int cnt = 0;
  
  digitalWrite(OUT_5V, HIGH); //Always 5V output (for switching)

  //Bluetooth connection after pressing the switch
  if (digitalRead(IN_5V))
  {
    init_bt();
  }

  //Transmission process to Bluetooth module (used when transmitting from serial monitor)
  if (Serial.available())
  {
    btSerial.print(char(Serial.read()));
    delay(100);
  }

  //Receive processing from Bluetooth module
  if (btSerial.available())
  {
    //Send the received value to the PC side
    Serial.print(btSerial.readStringUntil('_')); //Use Until because readString is slow (argument is terminating character)
    delay(100);
  }
}
    1. PC side (only this is Python)

scroll_screen_bt.py



import serial
import re
import pyautogui as pgui


def ctrl_screen():  # 0.Perform processing at 08sec intervals
    with serial.Serial('COM8', 9600, timeout=0.08, stopbits=serial.STOPBITS_TWO) as ser:

        while True:
            val = ser.readline()
            val = val.decode() #Convert bytes type to str type (unicode string)

            if val == 'UP':
                pgui.typewrite(['up'])  #Scroll up the screen
            elif val == 'DOWN':
                pgui.typewrite(['down'])  #Scroll down the screen


if __name__ == "__main__":

    ctrl_screen()

circuit

The circuit diagram of this system is shown below. I used draw.io for drawing. I wrote a circuit diagram for the first time, but it's free, easy to write, and convenient!

    1. Sender (ATtiny2313)

image.png

  1. Receiving side (Arduino Micro)

image.png

How to use

    1. Start the Python script on the PC side.
  1. Turn on both the master and slave. (Master only connects to PC)

    1. Press the switch on the master side to connect the Bluetooth modules. If the connection is successful, the blinking LED will be lit. Now ready image.png
  2. Press the switch on the slave side to scroll the PC screen up and down. image.png

Precautions for implementation

If you change the setting of ATtiny2313 to use an external crystal oscillator, of course, if you do not attach an external crystal oscillator, the microcomputer will not work or even write. An internal oscillator is enough! If you set it to use an external oscillator without an oscillator, you will not be able to do anything without an external oscillator (I am).

Also, when using the software serial library with Arduino, there are restrictions on the pins that can be used. Details below ↓ https://garretlab.web.fc2.com/arduino_reference/libraries/standard_libraries/SoftwareSerial/

Information that was used as a reference

In addition to the sites mentioned so far in this article, the following sites have been indebted. Thank you very much.

Contents Link destination
Basic usage of ATtiny2313 http://lumenbolk.com/?p=19
Solution for error caused by "import serial" https://teratail.com/questions/101843
PC(Python)Serial communication between and ardino https://qiita.com/Acqua_Alta/items/9f19afddc6db1e4d4286
Kbhit in Arduino()Usability of https://forum.arduino.cc/index.php?topic=294636.0
How to detect key event in Arduino https://www.quora.com/How-do-I-detect-a-keyboard-event-in-an-Arduino-IDE-program
Key operation method by Python https://www.lisz-works.com/entry/pyautogui-key
Key operation method by Arduino https://garretlab.web.fc2.com/arduino_reference/language/functions/usb/keyboard/write.html
How to receive character strings in Arduino serial communication https://ch.nicovideo.jp/yugata/blomaga/ar1177727

Finally

It's better to do this here ... or something wrong here! If you have any questions, sorry to trouble you, but if you can point it out, I will be happy to shed tears.

Recommended Posts

[Python / C] I made a device that wirelessly scrolls the screen of a PC remotely.
I made a slack bot that notifies me of the temperature
The goodness of the touch screen disappeared when the tablet PC was made into a Manjaro i3 environment
I made a calendar that automatically updates the distribution schedule of Vtuber
I made a program to check the size of a file in Python
I made a function to see the movement of a two-dimensional array (Python)
I made a script to record the active window using win32gui of Python
I made a github action that notifies Slack of the visual regression test
[Python] I made a web scraping code that automatically acquires the news title and URL of Nikkei Inc.
[Python] A program that counts the number of valleys
I made a VM that runs OpenCV for Python
Python points from the perspective of a C programmer
A memo that I touched the Datastore with python
[Python] A program that compares the positions of kangaroos.
I made a twitter app that decodes the characters of Pricone with heroku (failure)
I made a calendar that automatically updates the distribution schedule of Vtuber (Google Calendar edition)
I made a python text
I just changed the sample source of Python a little.
I made a function to check the model of DCGAN
I made a dot picture of the image of Irasutoya. (part1)
I made a dot picture of the image of Irasutoya. (part2)
A Python script that compares the contents of two directories
[Atcoder] [C ++] I made a test automation tool that can be used during the contest
I made a function to crop the image of python openCV, so please use it.
I made a program in Python that changes the 1-minute data of FX to an arbitrary time frame (1 hour frame, etc.)
I made a C ++ learning site
[Python] I made a Line bot that randomly asks English words.
[Python3] I made a decorator that declares undefined functions and methods.
I made a package that can compare morphological analyzers with Python
I made a Line-bot using Python!
I made a Line bot that guesses the gender and age of a person from an image
[Introduction to Python] I compared the naming conventions of C # and Python.
I made a fortune with Python.
A function that measures the processing time of a method in python
I made a shuffle that can be reset (reverted) with Python
I made a scaffolding tool for the Python web framework Bottle
I made a library that adds docstring to a Python stub file.
I made a daemon with Python
I made a program that automatically calculates the zodiac with tkinter
[python] A note that started to understand the behavior of matplotlib.pyplot
The story of making a module that skips mail with python
[python] I made a class that can write a file tree quickly
[Python] A program that rotates the contents of the list to the left
[Kaggle] I made a collection of questions using the Titanic tutorial
[Python] I analyzed the diary of a first-year member of society and made a positive / negative judgment on the life of a member of society.
[Python] I made a bot that tells me the current temperature when I enter a place name on LINE
[Python] A program that calculates the number of chocolate segments that meet the conditions
[AtCoder explanation] Control the A, B, C problems of ABC182 with Python!
[Python] I made a decorator that doesn't seem to have any use.
I made a web application in Python that converts Markdown to HTML
[Python] A program that calculates the number of socks to be paired
I made a Discord bot in Python that translates when it reacts
[Python] I made a utility that can access dict type like a path
I made a library konoha that switches the tokenizer to a nice feeling
[AtCoder explanation] Control the A, B, C problems of ABC187 with Python!
I made a tool that makes decompression a little easier with CLI (Python3)
[IOS] I made a widget that displays Qiita trends in Pythonista3. [Python]
I made a mistake in fetching the hierarchy with MultiIndex of pandas
Python: I want to measure the processing time of a function neatly
[AtCoder explanation] Control the A, B, C problems of ABC184 with Python!
[Python] Note: A self-made function that finds the area of the normal distribution