Pull to refresh

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

DIY


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



Что нам надо?


  • Носок
  • Провода
  • Ардуина
  • 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)
	}
}

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

Будьте здоровы, занимайтесь спортом.
Tags:
Hubs:
Total votes 16: ↑9 and ↓7 +2
Views 3K
Comments Comments 5