If You Play Air Drum, It Makes Real Drum Playing Physically.

Make things

If you play air drum on the table, it makes real drum playing physically depending on your hands position.

Materials

  • obniz x3
    (for distance sensor x1, for Servo Motor x2)
  • power supply for obniz x3
  • Servo Motor x2
  • GP2Y0A21YK0F(IR distance sensor) x2
  • mini drum and sticks x1
  • sticks for fixing x2
  • plastic tape x1
  • sheet drum positions are painted x1

How to make

Hardware Connection

Table

Connect two distance sensors to one obniz like the table and the image below. Then, supply power to the obniz.

obniz GP2Y0A21YK0F (IR distance sensor)
0 [sensor1] Vcc
1 [sensor1] GND
2 [sensor1] signal
6 [sensor2] Vcc
7 [sensor2] GND
8 [sensor2] signal

Put distance sensors side by side like the image below. (They are put a little diagonally in this image.)

If you place your hand close to left sensor, the left drum is beaten, and if you move your hand a little further away, the center drum is beaten.
If you place your hand close to right sensor, the cymbal is beaten, and if you move your hand a little further away, the right drum is beaten.
If you place your hand much further away from these sensor, none of these drums are beaten.

Drum

Connect one servo motor to one obniz like the table and the image below. Make two sets of this. Please prepare two power supplies for each.

obniz Servo Motor
9 signal
10 Vcc
11 GND

Put sticks to servo motors, and put these to the drums. One is for the left drum and the cymbal, the other is for the center drum and the right drum.

for the left drum and the cymbal

for the center drum and the right drum

It’s finished. If you run the program below, the drums are beaten depending on your hand’s position.

Program

This program is written in node.js. Not runnable on browser.

const Obniz = require("obniz");

const disObniz = new Obniz("OBNIZ_ID_FOR_DISTANCE_HERE");
const drumObnizes = [new Obniz("OBNIZ_ID_FOR_DRUM_1_HERE"), new Obniz("OBNIZ_ID_FOR_DRUM_2_HERE")];

//DEFAULT_SERVO_ANGLE is the angle of the servo motor
//please adjust this value properly
const DEFAULT_SERVO_ANGLE = 40.0;
const BACK_SERVO_PARAM = {default: 40.0, leftdrum: 125.0, cymbal: 12.0};
const FRONT_SERVO_PARAM = {default: 40.0, centerdrum: 88.0, rightdrum: 25.0};

disObniz.onconnect = async () => {
	
	let disLeft = disObniz.wired("GP2Y0A21YK0F", {vcc:0, gnd:1, signal:2});
	let disRight = disObniz.wired("GP2Y0A21YK0F", {vcc:6, gnd:7, signal:8});
	let servoMotors = [];
	
	drumObnizes.forEach(async (obniz, index) => {
		
		if(drumObnizes[index].connectionState === 'connected'){
			
			await console.log(drumObnizes[index].connectionState);
			let servo = obniz.wired("ServoMotor", {signal:9,vcc:10, gnd:11});
			servoMotors[index] = servo;
			
		}else{
			
			await drumObnizes[index].wait(500);
			let servo = obniz.wired("ServoMotor", {signal:9,vcc:10, gnd:11});
			servoMotors[index] = servo;
			await console.log(drumObnizes[index].connectionState);
			
		}
		
		await console.log(servoMotors.length + "motors");
	});
	
	const rotateServo = async (area, servoAngle) => {
		
		if(servoMotors[area] === undefined || servoMotors[area] === null){
			return;
		}

		await servoMotors[area].angle(servoAngle);
		await resetServo(area);
	}
	
	const resetServo = async area => {
		servoMotors.forEach(async (servo, index) => {
			if(index === area || drumObnizes[index].connectionState !== 'connected'){
				return;
			}
			await servo.angle(DEFAULT_SERVO_ANGLE);
		});
	}
	
	//for the first loop
	let prevArea = {left: 2, right: 2};
	let nowArea = {left: 3, right: 3};
	
	//area division(every 140mm)
	//left0 => upper left: left drum
	//right0 => upper right: cymbal
	//left1 => lower left: center drum
	//right1 => lower right: right drum
	const AREA_THRESHOLD = 140;
	
	while(true){

		
		let leftPos = await Math.floor(await disLeft.getWait() / AREA_THRESHOLD);
		let rightPos = await Math.floor(await disRight.getWait() / AREA_THRESHOLD);
		
		nowArea.left = leftPos;
		nowArea.right = rightPos;
		
		if(prevArea.left === nowArea.left && prevArea.right === nowArea.right){
			continue;
		}else if(prevArea.left > 1 && nowArea.left > 1 && prevArea.right > 1 && nowArea.right > 1){
			continue;
		}
		
		await console.log(nowArea);
		
		
		//area division
		if(nowArea.left > 1 || nowArea.right > 1){
			await console.log("out of area");
			await resetServo(nowArea);
		}
		if(nowArea.left === 0){
			await console.log("left drum");
			await rotateServo(nowArea.left, BACK_SERVO_PARAM.leftdrum);
			
		}else if(nowArea.left === 1){
			await console.log("center drum");
			await rotateServo(nowArea.left, FRONT_SERVO_PARAM.centerdrum);
			
		}
		if(nowArea.right === 0){
			await console.log("cymbal");
			await rotateServo(nowArea.right, BACK_SERVO_PARAM.cymbal);
			
		}else if(nowArea.right===1){
			await console.log("right drum");
			await rotateServo(nowArea.right, FRONT_SERVO_PARAM.rightdrum);
			
		}
		
		prevArea.left = nowArea.left;
		prevArea.right = nowArea.right;
		
	}

	
}