Носок киборг ваш тренер и друг

от автора


Человеку нужно двигаться, а работая, я постоянно или сижу, или лежу. Поэтому бывает я поднимаю ноги, но тут есть проблема. Я считаю сколько раз поднял ноги, а когда я считаю, то я не могу разговаривать или смотреть внимательно кино. Ситуация стала критичной, когда я решил досмотреть последнии серии Наруто. Поэтому я создал его!

Что нам надо?

  • Носок
  • Провода
  • Ардуина
  • MPU-6050 (GY-521) — самый дешевый и бесполезный гироскоп+акселерометр $1.80, но на носке работает на 5
  • Ноутбук с программой на Go

Первым делом надо соединить MPU-6050 c ардуино по I2C, и потом загрузить скетч с Arduino Playground для MPU-6050.

// MPU-6050 Short Example Sketch // By Arduino User JohnChi // August 17, 2014 // Public Domain #include<Wire.h> const int MPU=0x68;  // I2C address of the MPU-6050 int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; void setup(){   Wire.begin();   Wire.beginTransmission(MPU);   Wire.write(0x6B);  // PWR_MGMT_1 register   Wire.write(0);     // set to zero (wakes up the MPU-6050)   Wire.endTransmission(true);   Serial.begin(57600); } void loop(){   Wire.beginTransmission(MPU);   Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)   Wire.endTransmission(false);   Wire.requestFrom(MPU,14,true);  // request a total of 14 registers   AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)       AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)   AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)   Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)   GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)   GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)   GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)   Serial.print("AcX = "); Serial.print(AcX);   Serial.print(" | AcY = "); Serial.print(AcY);   Serial.print(" | AcZ = "); Serial.print(AcZ);   Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53);  //equation for temperature in degrees C from datasheet   Serial.print(" | GyX = "); Serial.print(GyX);   Serial.print(" | GyY = "); Serial.print(GyY);   Serial.print(" | GyZ = "); Serial.println(GyZ);   delay(333); } 

У меня ардуина при подключении отображается как /dev/ttyUSB0, на винде это будет COM c каким-то числом.

Вот моя программа на Go. Для проигрывания звуков я вызываю программу play, которой у вас может не быть, но тогда и звуков не будет. Ёё можно заменить на другую доступную вам программу.

package main  import ( 	"fmt" 	"math" 	"os/exec" 	"strings"  	"github.com/CossackPyra/pyraconv" 	"github.com/tarm/serial" )  var ( 	inited     bool = false 	startAngle float64 	state      int = 0 	counter        = 0 )  func main() {  	c := &serial.Config{Name: "/dev/ttyUSB0", Baud: 57600} 	s, err := serial.OpenPort(c) 	panicer(err)  	var b1 []byte  	buf := make([]byte, 128) 	for { 		n, err := s.Read(buf) 		panicer(err) 		// fmt.Println(n) 		// fmt.Print(string(buf[:n])) 		len1 := len(b1) 		b1 = append(b1, buf[:n]...) 		pos1 := -1 		for i1, by1 := range buf[:n] { 			if by1 == 10 { 				pos1 = i1 				break 			} 		} 		if pos1 != -1 { 			b2 := b1[:len1+pos1] 			b1 = b1[len1+pos1+1:] 			s1 := string(b2) 			// fmt.Println(ss1) 			ss1 := strings.Split(s1, " | ") 			if len(ss1) < 7 { 				continue 			} 			m1 := make(map[string]string) 			for _, s2 := range ss1 { 				ss2 := strings.Split(s2, " = ") 				if len(ss2) < 2 { 					continue 				} 				m1[ss2[0]] = ss2[1] 			} 			if len(m1) < 7 { 				continue 			} 			m2 := make(map[string]int) 			for k1, v1 := range m1 { 				m2[k1] = int(pyraconv.ToInt64(v1)) 			} 			processMap(m2) 		} 	}  }  func processMap(m1 map[string]int) { 	angle := math.Atan2(float64(m1["AcX"]), float64(m1["AcY"])) / math.Pi * 180.0 	delta := angle - startAngle 	if delta > 180.0 { 		delta -= 360.0 	} 	if delta < -180.0 { 		delta += 360.0 	} 	// fmt.Printf("%f %f %d %d %d %d %d %d\n", angle, delta, m1["AcX"], m1["AcY"], m1["AcZ"], m1["GyX"], m1["GyY"], m1["GyZ"]) 	if !inited { 		inited = true 		startAngle = angle 		state = 0 		return 	}  	if state == 0 { 		if delta > 60.0 { 			state = 1 			up() 		} 		if delta < -60.0 { 			state = -1 			up() 		} 	} 	if state == 1 { 		if delta < 30.0 { 			state = 0 			down() 		} 	} 	if state == -1 { 		if delta > -30.0 { 			state = 0 			down() 		} 	} }  func up() { 	fmt.Println("UP") }  func down() { 	counter++ 	fmt.Println("DOWN ", counter) 	if counter%100 == 0 { 		exec.Command("play", "~/my/applications/platformerFX/OGG/speedup.ogg").Output() 	} else if counter%50 == 0 { 		exec.Command("play", "~/my/applications/platformerFX/OGG/checkpoint.ogg").Output() 	} else if counter%20 == 0 { 		exec.Command("play", "~/my/applications/platformerFX/OGG/collect1_score1.ogg").Output() 	} else { 		exec.Command("play", "~/my/applications/platformerFX/OGG/button1.ogg").Output() 	} }  func panicer(err error) { 	if err != nil { 		panic(err) 	} } 

Разработкой я очень доволен. Сделать это все можно достаточно быстро, а так как код у вас есть, то еще быстрей!

Будьте здоровы, занимайтесь спортом.

ссылка на оригинал статьи http://habrahabr.ru/post/263803/