brick-pi 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +22 -0
- data/README.md +101 -0
- data/Rakefile +8 -0
- data/brick_pi.gemspec +23 -0
- data/ext/brick_pi/BrickPi.h +641 -0
- data/ext/brick_pi/extconf.rb +4 -0
- data/ext/brick_pi/native.c +65 -0
- data/ext/brick_pi/tick.h +46 -0
- data/lib/brick_pi.rb +4 -0
- data/lib/brick_pi/bot.rb +36 -0
- data/lib/brick_pi/motor.rb +19 -0
- data/lib/brick_pi/version.rb +3 -0
- metadata +92 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e63e867f917f20a008427c1096e7ba94b267c890
|
4
|
+
data.tar.gz: 78a16b7c6cb6a76bf6c94bcea3091a2e52d0eedb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 34a9ac8a0def422ffd6d6fb5109d58e52288ec7efdcb4058395c6433a2b186896468c9e8b19f8d5494397da5091a78de95978a6676ca1c1f4856c1b1d395b43b
|
7
|
+
data.tar.gz: 2d082af9c7dc6311e142864f3f7164328e0c190a21dd817faef757fa657249576245649beeebdcfb66a70e3fe8017f908bf63edf48f591d2632d87a8dc236d77
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Brandon Hays
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 TODO: Write your name
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# BrickBot: A BrickPi library for Ruby
|
2
|
+
|
3
|
+
ruby wrappers for the BrickPi Lego Mindstorms C library
|
4
|
+
|
5
|
+
TODO: Write a gem description
|
6
|
+
TODO: Tag, version, and publish as gem
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'brick_pi'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install brick_pi
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
Currently, you only get a set of primitives to run motors. Expect more functionality around sensors and a more robust library supporting various configurations (e.g. 2-tracked vehicle).
|
25
|
+
|
26
|
+
The Bot object starts and stops the robot. It contains 4 Motor objects, mapped to port A-D on your BrickPi.
|
27
|
+
|
28
|
+
Here's a quick & dirty script to spin a motor:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
require 'brick_pi'
|
32
|
+
|
33
|
+
# Instantiate the Bot
|
34
|
+
bot = BrickPi::Bot.new
|
35
|
+
|
36
|
+
# Set the speed for a motor, on a scale of 0 - 100
|
37
|
+
bot.motor1.spin 50
|
38
|
+
|
39
|
+
# Get this party started
|
40
|
+
bot.start
|
41
|
+
|
42
|
+
# Stop a single motor
|
43
|
+
bot.motor1.stop
|
44
|
+
|
45
|
+
# Stop all functions for a bot
|
46
|
+
bot.stop
|
47
|
+
```
|
48
|
+
|
49
|
+
Once your bot is started, you can change the speed or direction of the motors at any time with the `Motor#spin` method.
|
50
|
+
|
51
|
+
Here's a really yucky script I hacked together to let you drive a 2-tracked vehicle with an iCade 8-Bitty (which is basically a bluetooth keyboard that looks like an NES controller).
|
52
|
+
|
53
|
+
It requires the Highline gem, so on the BrickPi you'll need to run `gem install highline`.
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
require "highline/system_extensions"
|
57
|
+
include HighLine::SystemExtensions
|
58
|
+
HighLine::SystemExtensions.raw_no_echo_mode
|
59
|
+
|
60
|
+
bot = BrickPi::Bot.new
|
61
|
+
bot.start
|
62
|
+
|
63
|
+
speed = 20
|
64
|
+
loop do
|
65
|
+
char = HighLine::SystemExtensions.get_character
|
66
|
+
case char.chr
|
67
|
+
when 'w'
|
68
|
+
bot.motor1.spin speed
|
69
|
+
bot.motor2.spin speed
|
70
|
+
when 'd'
|
71
|
+
bot.motor1.spin speed
|
72
|
+
bot.motor2.spin 0 - speed
|
73
|
+
when 'a'
|
74
|
+
bot.motor1.spin 0 - speed
|
75
|
+
bot.motor2.spin speed
|
76
|
+
when 'x'
|
77
|
+
bot.motor1.spin 0 - speed
|
78
|
+
bot.motor2.spin 0 - speed
|
79
|
+
when 'o'
|
80
|
+
if speed >=0 && speed <= 80
|
81
|
+
speed += 20
|
82
|
+
end
|
83
|
+
when 'l'
|
84
|
+
if speed > 20 && speed <= 100
|
85
|
+
speed -= 20
|
86
|
+
end
|
87
|
+
when 'e', 'c', 'z', 'q'
|
88
|
+
bot.motor1.stop
|
89
|
+
bot.motor2.stop
|
90
|
+
end
|
91
|
+
sleep(5 / 1000)
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
## Contributing
|
96
|
+
|
97
|
+
1. Fork it ( https://github.com/tehviking/brick_pi/fork )
|
98
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
99
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
100
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
101
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/brick_pi.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'brick_pi/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "brick-pi"
|
8
|
+
spec.version = BrickPi::VERSION
|
9
|
+
spec.authors = ["Brandon Hays", "Charles Lowell"]
|
10
|
+
spec.email = ["brandon.hays@gmail.com"]
|
11
|
+
spec.summary = %q{Ruby library to run the BrickPi drivers for Lego Mindstorms}
|
12
|
+
spec.description = %q{BrickPi uses a C library to communicate with Lego Mindstorms motors and sensors via GPIO on the Raspberry Pi. This library wraps the C and exposes a nicer, object-oriented interface via Ruby.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib", "ext"]
|
20
|
+
spec.extensions = ["ext/brick_pi/extconf.rb"]
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
@@ -0,0 +1,641 @@
|
|
1
|
+
/*
|
2
|
+
* Matthew Richardson
|
3
|
+
* matthewrichardson37<at>gmail.com
|
4
|
+
* http://mattallen37.wordpress.com/
|
5
|
+
*
|
6
|
+
* Updated by John Cole, Dexter Industries.
|
7
|
+
*
|
8
|
+
* Initial date: June 4, 2013
|
9
|
+
* Last updated: Oct 7, 2013
|
10
|
+
*
|
11
|
+
* These files have been made available online through a Creative Commons Attribution-ShareAlike 3.0 license.
|
12
|
+
* (http://creativecommons.org/licenses/by-sa/3.0/)
|
13
|
+
*
|
14
|
+
* This is a library of functions for the RPi to communicate with the BrickPi.
|
15
|
+
*/
|
16
|
+
/*
|
17
|
+
##################################################################################################################
|
18
|
+
* Debugging:
|
19
|
+
* - NOTE THAT DEBUGGING ERROR MESSAGES ARE TURNED OFF BY DEFAULT. To debug, just take the comment out of Line 38.
|
20
|
+
*
|
21
|
+
* If you #define DEBUG in the program, the BrickPi.h drivers will print debug messages to the terminal. One common message is
|
22
|
+
* "BrickPiRx error: -2", in function BrickPiUpdateValues(). This is caused by an error in the communication with one of the
|
23
|
+
* microcontrollers on the BrickPi. When this happens, the drivers automatically re-try the communication several times before the
|
24
|
+
* function gives up and returns -1 (unsuccessful) to the user-program.
|
25
|
+
|
26
|
+
* Function BrickPiUpdateValues() will either return 0 (success), or -1 (error that could not automatically be resolved, even after
|
27
|
+
* re-trying several times). We have rarely had BrickPiUpdateValues() retry more than once before the communication was successful.
|
28
|
+
* A known cause for "BrickPiRx error: -2" is the RPi splitting the UART message. Sometimes the RPi will send e.g. 3 bytes, wait a
|
29
|
+
* while, and then send 4 more, when it should have just sent 7 at once. During the pause between the packs of bytes, the BrickPi
|
30
|
+
* microcontrollers will think the transmission is complete, realize the message doesn't make sense, throw it away, and not return
|
31
|
+
* a message to the RPi. The RPi will then fail to receive a message in the specified amount of time, timeout, and then retry the
|
32
|
+
* communication.
|
33
|
+
*/
|
34
|
+
|
35
|
+
#ifndef __BrickPi_h_
|
36
|
+
#define __BrickPi_h_
|
37
|
+
|
38
|
+
// #define DEBUG
|
39
|
+
|
40
|
+
#include <wiringPi.h>
|
41
|
+
|
42
|
+
#define PORT_A 0
|
43
|
+
#define PORT_B 1
|
44
|
+
#define PORT_C 2
|
45
|
+
#define PORT_D 3
|
46
|
+
|
47
|
+
#define PORT_1 0
|
48
|
+
#define PORT_2 1
|
49
|
+
#define PORT_3 2
|
50
|
+
#define PORT_4 3
|
51
|
+
|
52
|
+
#define MASK_D0_M 0x01
|
53
|
+
#define MASK_D1_M 0x02
|
54
|
+
#define MASK_9V 0x04
|
55
|
+
#define MASK_D0_S 0x08
|
56
|
+
#define MASK_D1_S 0x10
|
57
|
+
|
58
|
+
#define BYTE_MSG_TYPE 0 // MSG_TYPE is the first byte.
|
59
|
+
#define MSG_TYPE_CHANGE_ADDR 1 // Change the UART address.
|
60
|
+
#define MSG_TYPE_SENSOR_TYPE 2 // Change/set the sensor type.
|
61
|
+
#define MSG_TYPE_VALUES 3 // Set the motor speed and direction, and return the sesnors and encoders.
|
62
|
+
#define MSG_TYPE_E_STOP 4 // Float motors immidately
|
63
|
+
#define MSG_TYPE_TIMEOUT_SETTINGS 5 // Set the timeout
|
64
|
+
|
65
|
+
// New UART address (MSG_TYPE_CHANGE_ADDR)
|
66
|
+
#define BYTE_NEW_ADDRESS 1
|
67
|
+
|
68
|
+
// Sensor setup (MSG_TYPE_SENSOR_TYPE)
|
69
|
+
#define BYTE_SENSOR_1_TYPE 1
|
70
|
+
#define BYTE_SENSOR_2_TYPE 2
|
71
|
+
|
72
|
+
// Timeout setup (MSG_TYPE_TIMEOUT_SETTINGS)
|
73
|
+
#define BYTE_TIMEOUT 1
|
74
|
+
|
75
|
+
#define TYPE_MOTOR_PWM 0
|
76
|
+
#define TYPE_MOTOR_SPEED 1
|
77
|
+
#define TYPE_MOTOR_POSITION 2
|
78
|
+
|
79
|
+
#define TYPE_SENSOR_RAW 0 // - 31
|
80
|
+
#define TYPE_SENSOR_LIGHT_OFF 0
|
81
|
+
#define TYPE_SENSOR_LIGHT_ON (MASK_D0_M | MASK_D0_S)
|
82
|
+
#define TYPE_SENSOR_TOUCH 32
|
83
|
+
#define TYPE_SENSOR_ULTRASONIC_CONT 33
|
84
|
+
#define TYPE_SENSOR_ULTRASONIC_SS 34
|
85
|
+
#define TYPE_SENSOR_RCX_LIGHT 35 // tested minimally
|
86
|
+
#define TYPE_SENSOR_COLOR_FULL 36
|
87
|
+
#define TYPE_SENSOR_COLOR_RED 37
|
88
|
+
#define TYPE_SENSOR_COLOR_GREEN 38
|
89
|
+
#define TYPE_SENSOR_COLOR_BLUE 39
|
90
|
+
#define TYPE_SENSOR_COLOR_NONE 40
|
91
|
+
#define TYPE_SENSOR_I2C 41
|
92
|
+
#define TYPE_SENSOR_I2C_9V 42
|
93
|
+
|
94
|
+
#define BIT_I2C_MID 0x01 // Do one of those funny clock pulses between writing and reading. defined for each device.
|
95
|
+
#define BIT_I2C_SAME 0x02 // The transmit data, and the number of bytes to read and write isn't going to change. defined for each device.
|
96
|
+
|
97
|
+
#define INDEX_RED 0
|
98
|
+
#define INDEX_GREEN 1
|
99
|
+
#define INDEX_BLUE 2
|
100
|
+
#define INDEX_BLANK 3
|
101
|
+
|
102
|
+
void BrickPiTx(unsigned char dest, unsigned char ByteCount, unsigned char OutArray[]);
|
103
|
+
|
104
|
+
struct BrickPiStruct{
|
105
|
+
unsigned char Address [2]; // Communication addresses
|
106
|
+
unsigned long Timeout ; // Communication timeout (how long in ms since the last valid communication before floating the motors). 0 disables the timeout.
|
107
|
+
|
108
|
+
/*
|
109
|
+
Motors
|
110
|
+
*/
|
111
|
+
int MotorSpeed [4]; // Motor speeds, from -255 to 255
|
112
|
+
unsigned char MotorEnable [4]; // Motor enable/disable
|
113
|
+
|
114
|
+
/*
|
115
|
+
Encoders
|
116
|
+
*/
|
117
|
+
long EncoderOffset [4]; // Encoder offsets (not yet implemented)
|
118
|
+
long Encoder [4]; // Encoder values
|
119
|
+
|
120
|
+
/*
|
121
|
+
Sensors
|
122
|
+
*/
|
123
|
+
long Sensor [4]; // Primary sensor values
|
124
|
+
long SensorArray [4][4]; // For more sensor values for the sensor (e.g. for color sensor FULL mode).
|
125
|
+
unsigned char SensorType [4]; // Sensor types
|
126
|
+
unsigned char SensorSettings [4][8]; // Sensor settings, used for specifying I2C settings.
|
127
|
+
|
128
|
+
/*
|
129
|
+
I2C
|
130
|
+
*/
|
131
|
+
unsigned char SensorI2CDevices[4]; // How many I2C devices are on each bus (1 - 8).
|
132
|
+
unsigned char SensorI2CSpeed [4]; // The I2C speed.
|
133
|
+
unsigned char SensorI2CAddr [4][8]; // The I2C address of each device on each bus.
|
134
|
+
unsigned char SensorI2CWrite [4][8]; // How many bytes to write
|
135
|
+
unsigned char SensorI2CRead [4][8]; // How many bytes to read
|
136
|
+
unsigned char SensorI2COut [4][8][16]; // The I2C bytes to write
|
137
|
+
unsigned char SensorI2CIn [4][8][16]; // The I2C input buffers
|
138
|
+
};
|
139
|
+
|
140
|
+
struct BrickPiStruct BrickPi;
|
141
|
+
|
142
|
+
//Store the button's of the MINDSENSORS PSP Controller
|
143
|
+
struct button
|
144
|
+
{
|
145
|
+
unsigned char l1;
|
146
|
+
unsigned char l2;
|
147
|
+
unsigned char r1;
|
148
|
+
unsigned char r2;
|
149
|
+
unsigned char a;
|
150
|
+
unsigned char b;
|
151
|
+
unsigned char c;
|
152
|
+
unsigned char d;
|
153
|
+
unsigned char tri;
|
154
|
+
unsigned char sqr;
|
155
|
+
unsigned char cir;
|
156
|
+
unsigned char cro;
|
157
|
+
unsigned char ljb; // joystick button state
|
158
|
+
unsigned char rjb; // joystick button state
|
159
|
+
|
160
|
+
int ljx; // analog value of joystick scaled from -127 to 127
|
161
|
+
int ljy; // analog value of joystick scaled from -127 to 127
|
162
|
+
int rjx; // analog value of joystick scaled from -127 to 127
|
163
|
+
int rjy; // analog value of joystick scaled from -127 to 127
|
164
|
+
};
|
165
|
+
//Initialize all the buttons to 0 of the MINDSENSORS PSP controller
|
166
|
+
struct button init_psp (struct button b)
|
167
|
+
{
|
168
|
+
b.l1 = 0;
|
169
|
+
b.l2 = 0;
|
170
|
+
b.r1 = 0;
|
171
|
+
b.r2 = 0;
|
172
|
+
b.a = 0;
|
173
|
+
b.b = 0;
|
174
|
+
b.c = 0;
|
175
|
+
b.d = 0;
|
176
|
+
b.tri = 0;
|
177
|
+
b.sqr = 0;
|
178
|
+
b.cir = 0;
|
179
|
+
b.cro = 0;
|
180
|
+
b.ljb = 0;
|
181
|
+
b.rjb = 0;
|
182
|
+
b.ljx = 0;
|
183
|
+
b.ljy = 0;
|
184
|
+
b.rjx = 0;
|
185
|
+
b.rjy = 0;
|
186
|
+
return b;
|
187
|
+
}
|
188
|
+
|
189
|
+
//Update all the buttons of the MINDSENSORS PSP controller
|
190
|
+
//For all buttons:
|
191
|
+
// 0: Unpressed
|
192
|
+
// 1: Pressed
|
193
|
+
//
|
194
|
+
// Left and right joystick: -127 to 127
|
195
|
+
struct button upd(struct button b,int port)
|
196
|
+
{
|
197
|
+
//Left and right joystick button press
|
198
|
+
b.ljb = ~(BrickPi.SensorI2CIn[port][0][0] >> 1) & 0x01;
|
199
|
+
b.rjb = ~(BrickPi.SensorI2CIn[port][0][0] >> 2) & 0x01;
|
200
|
+
|
201
|
+
//For buttons a,b,c,d
|
202
|
+
b.d = ~(BrickPi.SensorI2CIn[port][0][0] >> 4) & 0x01;
|
203
|
+
b.c = ~(BrickPi.SensorI2CIn[port][0][0] >> 5) & 0x01;
|
204
|
+
b.b = ~(BrickPi.SensorI2CIn[port][0][0] >> 6) & 0x01;
|
205
|
+
b.a = ~(BrickPi.SensorI2CIn[port][0][0] >> 7) & 0x01;
|
206
|
+
|
207
|
+
//For buttons l1,l2,r1,r2
|
208
|
+
b.l2 = ~(BrickPi.SensorI2CIn[port][0][1] ) & 0x01;
|
209
|
+
b.r2 = ~(BrickPi.SensorI2CIn[port][0][1] >> 1) & 0x01;
|
210
|
+
b.l1 = ~(BrickPi.SensorI2CIn[port][0][1] >> 2) & 0x01;
|
211
|
+
b.r1 = ~(BrickPi.SensorI2CIn[port][0][1] >> 3) & 0x01;
|
212
|
+
|
213
|
+
//For buttons square,triangle,cross,circle
|
214
|
+
b.tri = ~(BrickPi.SensorI2CIn[port][0][1] >> 4) & 0x01;
|
215
|
+
b.cir = ~(BrickPi.SensorI2CIn[port][0][1] >> 5) & 0x01;
|
216
|
+
b.cro = ~(BrickPi.SensorI2CIn[port][0][1] >> 6) & 0x01;
|
217
|
+
b.sqr = ~(BrickPi.SensorI2CIn[port][0][1] >> 7) & 0x01;
|
218
|
+
|
219
|
+
//Left joystick x and y , -127 to 127
|
220
|
+
b.ljx = -1*((BrickPi.SensorI2CIn[port][0][5]&0xff) - 128);
|
221
|
+
b.ljy = (BrickPi.SensorI2CIn[port][0][4]&0xff) - 128;
|
222
|
+
|
223
|
+
//Right joystick x and y , -127 to 127
|
224
|
+
b.rjx = -1*((BrickPi.SensorI2CIn[port][0][3]&0xff) - 128);
|
225
|
+
b.rjy = (BrickPi.SensorI2CIn[port][0][2]&0xff) - 128;
|
226
|
+
return b;
|
227
|
+
}
|
228
|
+
//Show button values of the MINDSENSORS PSP controller
|
229
|
+
void show_val(struct button b)
|
230
|
+
{
|
231
|
+
printf("ljb rjb d c b a l2 r2 l1 r1 tri cir cro sqr\tljx\tljy\trjx\trjy\n");
|
232
|
+
printf("%d ",b.ljb);
|
233
|
+
printf(" %d ",b.rjb);
|
234
|
+
printf(" %d ",b.d);
|
235
|
+
printf("%d ",b.c);
|
236
|
+
printf("%d ",b.b);
|
237
|
+
printf("%d ",b.a);
|
238
|
+
|
239
|
+
printf("%d ",b.l2);
|
240
|
+
printf(" %d ",b.r2);
|
241
|
+
printf(" %d ",b.l1);
|
242
|
+
printf(" %d ",b.r1);
|
243
|
+
printf(" %d ",b.tri);
|
244
|
+
printf(" %d ",b.cir);
|
245
|
+
printf(" %d ",b.cro);
|
246
|
+
printf(" %d ",b.sqr);
|
247
|
+
printf("\t%d ",b.ljx);
|
248
|
+
printf("\t%d ",b.rjx);
|
249
|
+
printf("\t%d ",b.ljy);
|
250
|
+
printf("\t%d\n\n",b.rjy);
|
251
|
+
}
|
252
|
+
unsigned char Array[256];
|
253
|
+
unsigned char BytesReceived;
|
254
|
+
|
255
|
+
int BrickPiChangeAddress(unsigned char OldAddr, unsigned char NewAddr){
|
256
|
+
unsigned char i = 0;
|
257
|
+
Array[BYTE_MSG_TYPE] = MSG_TYPE_CHANGE_ADDR;
|
258
|
+
Array[BYTE_NEW_ADDRESS] = NewAddr;
|
259
|
+
BrickPiTx(OldAddr, 2, Array);
|
260
|
+
|
261
|
+
if(BrickPiRx(&BytesReceived, Array, 5000))
|
262
|
+
return -1;
|
263
|
+
if(!(BytesReceived == 1 && Array[BYTE_MSG_TYPE] == MSG_TYPE_CHANGE_ADDR))
|
264
|
+
return -1;
|
265
|
+
|
266
|
+
return 0;
|
267
|
+
}
|
268
|
+
|
269
|
+
int BrickPiSetTimeout(){
|
270
|
+
unsigned char i = 0;
|
271
|
+
while(i < 2){
|
272
|
+
Array[BYTE_MSG_TYPE] = MSG_TYPE_TIMEOUT_SETTINGS;
|
273
|
+
Array[BYTE_TIMEOUT ] = ( BrickPi.Timeout & 0xFF);
|
274
|
+
Array[(BYTE_TIMEOUT + 1)] = ((BrickPi.Timeout / 256 ) & 0xFF);
|
275
|
+
Array[(BYTE_TIMEOUT + 2)] = ((BrickPi.Timeout / 65536 ) & 0xFF);
|
276
|
+
Array[(BYTE_TIMEOUT + 3)] = ((BrickPi.Timeout / 16777216) & 0xFF);
|
277
|
+
BrickPiTx(BrickPi.Address[i], 5, Array);
|
278
|
+
if(BrickPiRx(&BytesReceived, Array, 2500))
|
279
|
+
return -1;
|
280
|
+
if(!(BytesReceived == 1 && Array[BYTE_MSG_TYPE] == MSG_TYPE_TIMEOUT_SETTINGS))
|
281
|
+
return -1;
|
282
|
+
i++;
|
283
|
+
}
|
284
|
+
return 0;
|
285
|
+
}
|
286
|
+
|
287
|
+
unsigned int Bit_Offset = 0;
|
288
|
+
|
289
|
+
void AddBits(unsigned char byte_offset, unsigned char bit_offset, unsigned char bits, unsigned long value){
|
290
|
+
unsigned char i = 0;
|
291
|
+
while(i < bits){
|
292
|
+
if(value & 0x01){
|
293
|
+
Array[(byte_offset + ((bit_offset + Bit_Offset + i) / 8))] |= (0x01 << ((bit_offset + Bit_Offset + i) % 8));
|
294
|
+
}
|
295
|
+
value /= 2;
|
296
|
+
i++;
|
297
|
+
}
|
298
|
+
Bit_Offset += bits;
|
299
|
+
}
|
300
|
+
|
301
|
+
unsigned long GetBits(unsigned char byte_offset, unsigned char bit_offset, unsigned char bits){
|
302
|
+
unsigned long Result = 0;
|
303
|
+
char i = bits;
|
304
|
+
while(i){
|
305
|
+
Result *= 2;
|
306
|
+
Result |= ((Array[(byte_offset + ((bit_offset + Bit_Offset + (i - 1)) / 8))] >> ((bit_offset + Bit_Offset + (i - 1)) % 8)) & 0x01);
|
307
|
+
i--;
|
308
|
+
}
|
309
|
+
Bit_Offset += bits;
|
310
|
+
return Result;
|
311
|
+
}
|
312
|
+
|
313
|
+
unsigned char BitsNeeded(unsigned long value){
|
314
|
+
unsigned char i = 0;
|
315
|
+
while(i < 32){
|
316
|
+
if(!value)
|
317
|
+
return i;
|
318
|
+
value /= 2;
|
319
|
+
i++;
|
320
|
+
}
|
321
|
+
return 31;
|
322
|
+
}
|
323
|
+
|
324
|
+
int BrickPiSetupSensors(){
|
325
|
+
unsigned char i = 0;
|
326
|
+
while(i < 2){
|
327
|
+
int ii = 0;
|
328
|
+
while(ii < 256){
|
329
|
+
Array[ii] = 0;
|
330
|
+
ii++;
|
331
|
+
}
|
332
|
+
Bit_Offset = 0;
|
333
|
+
Array[BYTE_MSG_TYPE] = MSG_TYPE_SENSOR_TYPE;
|
334
|
+
Array[BYTE_SENSOR_1_TYPE] = BrickPi.SensorType[PORT_1 + (i * 2)];
|
335
|
+
Array[BYTE_SENSOR_2_TYPE] = BrickPi.SensorType[PORT_2 + (i * 2)];
|
336
|
+
ii = 0;
|
337
|
+
while(ii < 2){
|
338
|
+
unsigned char port = (i * 2) + ii;
|
339
|
+
if(Array[BYTE_SENSOR_1_TYPE + ii] == TYPE_SENSOR_I2C
|
340
|
+
|| Array[BYTE_SENSOR_1_TYPE + ii] == TYPE_SENSOR_I2C_9V){
|
341
|
+
AddBits(3, 0, 8, BrickPi.SensorI2CSpeed[port]);
|
342
|
+
|
343
|
+
if(BrickPi.SensorI2CDevices[port] > 8)
|
344
|
+
BrickPi.SensorI2CDevices[port] = 8;
|
345
|
+
|
346
|
+
if(BrickPi.SensorI2CDevices[port] == 0)
|
347
|
+
BrickPi.SensorI2CDevices[port] = 1;
|
348
|
+
|
349
|
+
AddBits(3, 0, 3, (BrickPi.SensorI2CDevices[port] - 1));
|
350
|
+
|
351
|
+
unsigned char device = 0;
|
352
|
+
while(device < BrickPi.SensorI2CDevices[port]){
|
353
|
+
AddBits(3, 0, 7, (BrickPi.SensorI2CAddr[port][device] >> 1));
|
354
|
+
AddBits(3, 0, 2, BrickPi.SensorSettings[port][device]);
|
355
|
+
if(BrickPi.SensorSettings[port][device] & BIT_I2C_SAME){
|
356
|
+
AddBits(3, 0, 4, BrickPi.SensorI2CWrite[port][device]);
|
357
|
+
AddBits(3, 0, 4, BrickPi.SensorI2CRead [port][device]);
|
358
|
+
unsigned char out_byte = 0;
|
359
|
+
while(out_byte < BrickPi.SensorI2CWrite[port][device]){
|
360
|
+
AddBits(3, 0, 8, BrickPi.SensorI2COut[port][device][out_byte]);
|
361
|
+
out_byte++;
|
362
|
+
}
|
363
|
+
}
|
364
|
+
device++;
|
365
|
+
}
|
366
|
+
}
|
367
|
+
ii++;
|
368
|
+
}
|
369
|
+
unsigned char UART_TX_BYTES = (((Bit_Offset + 7) / 8) + 3);
|
370
|
+
BrickPiTx(BrickPi.Address[i], UART_TX_BYTES, Array);
|
371
|
+
if(BrickPiRx(&BytesReceived, Array, 500000))
|
372
|
+
return -1;
|
373
|
+
if(!(BytesReceived == 1 && Array[BYTE_MSG_TYPE] == MSG_TYPE_SENSOR_TYPE))
|
374
|
+
return -1;
|
375
|
+
i++;
|
376
|
+
}
|
377
|
+
return 0;
|
378
|
+
}
|
379
|
+
|
380
|
+
unsigned char Retried = 0; // For re-trying a failed update.
|
381
|
+
|
382
|
+
int BrickPiUpdateValues(){
|
383
|
+
unsigned char i = 0;
|
384
|
+
unsigned int ii = 0;
|
385
|
+
while(i < 2){
|
386
|
+
Retried = 0;
|
387
|
+
|
388
|
+
__RETRY_COMMUNICATION__:
|
389
|
+
|
390
|
+
ii = 0;
|
391
|
+
while(ii < 256){
|
392
|
+
Array[ii] = 0;
|
393
|
+
ii++;
|
394
|
+
}
|
395
|
+
|
396
|
+
Array[BYTE_MSG_TYPE] = MSG_TYPE_VALUES;
|
397
|
+
|
398
|
+
Bit_Offset = 0;
|
399
|
+
|
400
|
+
// AddBits(1, 0, 2, 0); use this to disable encoder offset
|
401
|
+
|
402
|
+
ii = 0; // use this for encoder offset support
|
403
|
+
while(ii < 2){
|
404
|
+
unsigned char port = (i * 2) + ii;
|
405
|
+
if(BrickPi.EncoderOffset[port]){
|
406
|
+
long Temp_Value = BrickPi.EncoderOffset[port];
|
407
|
+
unsigned char Temp_ENC_DIR;
|
408
|
+
unsigned char Temp_BitsNeeded;
|
409
|
+
|
410
|
+
AddBits(1, 0, 1, 1);
|
411
|
+
if(Temp_Value < 0){
|
412
|
+
Temp_ENC_DIR = 1;
|
413
|
+
Temp_Value *= (-1);
|
414
|
+
}
|
415
|
+
Temp_BitsNeeded = (BitsNeeded(Temp_Value) + 1);
|
416
|
+
AddBits(1, 0, 5, Temp_BitsNeeded);
|
417
|
+
Temp_Value *= 2;
|
418
|
+
Temp_Value |= Temp_ENC_DIR;
|
419
|
+
AddBits(1, 0, Temp_BitsNeeded, Temp_Value);
|
420
|
+
}
|
421
|
+
else{
|
422
|
+
AddBits(1, 0, 1, 0);
|
423
|
+
}
|
424
|
+
ii++;
|
425
|
+
}
|
426
|
+
|
427
|
+
int speed;
|
428
|
+
unsigned char dir;
|
429
|
+
ii = 0;
|
430
|
+
while(ii < 2){
|
431
|
+
unsigned char port = (i * 2) + ii;
|
432
|
+
speed = BrickPi.MotorSpeed[port];
|
433
|
+
dir = 0;
|
434
|
+
if(speed < 0){
|
435
|
+
dir = 1;
|
436
|
+
speed *= (-1);
|
437
|
+
}
|
438
|
+
if(speed > 255){
|
439
|
+
speed = 255;
|
440
|
+
}
|
441
|
+
AddBits(1, 0, 10, ((((speed & 0xFF) << 2) | (dir << 1) | (BrickPi.MotorEnable[port] & 0x01)) & 0x3FF));
|
442
|
+
ii++;
|
443
|
+
}
|
444
|
+
|
445
|
+
ii = 0;
|
446
|
+
while(ii < 2){
|
447
|
+
unsigned char port = (i * 2) + ii;
|
448
|
+
if(BrickPi.SensorType[port] == TYPE_SENSOR_I2C
|
449
|
+
|| BrickPi.SensorType[port] == TYPE_SENSOR_I2C_9V){
|
450
|
+
unsigned char device = 0;
|
451
|
+
while(device < BrickPi.SensorI2CDevices[port]){
|
452
|
+
if(!(BrickPi.SensorSettings[port][device] & BIT_I2C_SAME)){
|
453
|
+
AddBits(1, 0, 4, BrickPi.SensorI2CWrite[port][device]);
|
454
|
+
AddBits(1, 0, 4, BrickPi.SensorI2CRead [port][device]);
|
455
|
+
unsigned char out_byte = 0;
|
456
|
+
while(out_byte < BrickPi.SensorI2CWrite[port][device]){
|
457
|
+
AddBits(1, 0, 8, BrickPi.SensorI2COut[port][device][out_byte]);
|
458
|
+
out_byte++;
|
459
|
+
}
|
460
|
+
}
|
461
|
+
device++;
|
462
|
+
}
|
463
|
+
}
|
464
|
+
ii++;
|
465
|
+
}
|
466
|
+
|
467
|
+
unsigned char UART_TX_BYTES = (((Bit_Offset + 7) / 8) + 1);
|
468
|
+
BrickPiTx(BrickPi.Address[i], UART_TX_BYTES, Array);
|
469
|
+
|
470
|
+
int result = BrickPiRx(&BytesReceived, Array, 7500);
|
471
|
+
|
472
|
+
if(result != -2){ // -2 is the only error that indicates that the BrickPi uC did not properly receive the message
|
473
|
+
BrickPi.EncoderOffset[((i * 2) + PORT_A)] = 0;
|
474
|
+
BrickPi.EncoderOffset[((i * 2) + PORT_B)] = 0;
|
475
|
+
}
|
476
|
+
|
477
|
+
if(result || (Array[BYTE_MSG_TYPE] != MSG_TYPE_VALUES)){
|
478
|
+
#ifdef DEBUG
|
479
|
+
printf("BrickPiRx error: %d\n", result);
|
480
|
+
#endif
|
481
|
+
if(Retried < 2){
|
482
|
+
Retried++;
|
483
|
+
goto __RETRY_COMMUNICATION__;
|
484
|
+
}
|
485
|
+
else{
|
486
|
+
#ifdef DEBUG
|
487
|
+
printf("Retry failed.\n");
|
488
|
+
#endif
|
489
|
+
return -1;
|
490
|
+
}
|
491
|
+
}
|
492
|
+
|
493
|
+
Bit_Offset = 0;
|
494
|
+
|
495
|
+
unsigned char Temp_BitsUsed[2] = {0, 0}; // Used for encoder values
|
496
|
+
Temp_BitsUsed[0] = GetBits(1, 0, 5);
|
497
|
+
Temp_BitsUsed[1] = GetBits(1, 0, 5);
|
498
|
+
unsigned long Temp_EncoderVal;
|
499
|
+
|
500
|
+
ii = 0;
|
501
|
+
while(ii < 2){
|
502
|
+
Temp_EncoderVal = GetBits(1, 0, Temp_BitsUsed[ii]);
|
503
|
+
if(Temp_EncoderVal & 0x01){
|
504
|
+
Temp_EncoderVal /= 2;
|
505
|
+
BrickPi.Encoder[ii + (i * 2)] = Temp_EncoderVal * (-1);}
|
506
|
+
else{
|
507
|
+
BrickPi.Encoder[ii + (i * 2)] = (Temp_EncoderVal / 2);}
|
508
|
+
ii++;
|
509
|
+
}
|
510
|
+
|
511
|
+
ii = 0;
|
512
|
+
while(ii < 2){
|
513
|
+
unsigned char port = ii + (i * 2);
|
514
|
+
switch(BrickPi.SensorType[port]){
|
515
|
+
case TYPE_SENSOR_TOUCH:
|
516
|
+
BrickPi.Sensor[port] = GetBits(1, 0, 1);
|
517
|
+
break;
|
518
|
+
case TYPE_SENSOR_ULTRASONIC_CONT:
|
519
|
+
case TYPE_SENSOR_ULTRASONIC_SS:
|
520
|
+
BrickPi.Sensor[port] = GetBits(1, 0, 8);
|
521
|
+
break;
|
522
|
+
case TYPE_SENSOR_COLOR_FULL:
|
523
|
+
BrickPi.Sensor[port] = GetBits(1, 0, 3);
|
524
|
+
BrickPi.SensorArray[port][INDEX_BLANK] = GetBits(1, 0, 10);
|
525
|
+
BrickPi.SensorArray[port][INDEX_RED ] = GetBits(1, 0, 10);
|
526
|
+
BrickPi.SensorArray[port][INDEX_GREEN] = GetBits(1, 0, 10);
|
527
|
+
BrickPi.SensorArray[port][INDEX_BLUE ] = GetBits(1, 0, 10);
|
528
|
+
break;
|
529
|
+
case TYPE_SENSOR_I2C:
|
530
|
+
case TYPE_SENSOR_I2C_9V:
|
531
|
+
BrickPi.Sensor[port] = GetBits(1, 0, BrickPi.SensorI2CDevices[port]);
|
532
|
+
unsigned char device = 0;
|
533
|
+
while(device < BrickPi.SensorI2CDevices[port]){
|
534
|
+
if(BrickPi.Sensor[port] & (0x01 << device)){
|
535
|
+
unsigned char in_byte = 0;
|
536
|
+
while(in_byte < BrickPi.SensorI2CRead[port][device]){
|
537
|
+
BrickPi.SensorI2CIn[port][device][in_byte] = GetBits(1, 0, 8);
|
538
|
+
in_byte++;
|
539
|
+
}
|
540
|
+
}
|
541
|
+
device++;
|
542
|
+
}
|
543
|
+
break;
|
544
|
+
case TYPE_SENSOR_LIGHT_OFF:
|
545
|
+
case TYPE_SENSOR_LIGHT_ON:
|
546
|
+
case TYPE_SENSOR_RCX_LIGHT:
|
547
|
+
case TYPE_SENSOR_COLOR_RED:
|
548
|
+
case TYPE_SENSOR_COLOR_GREEN:
|
549
|
+
case TYPE_SENSOR_COLOR_BLUE:
|
550
|
+
case TYPE_SENSOR_COLOR_NONE:
|
551
|
+
default:
|
552
|
+
BrickPi.Sensor[(ii + (i * 2))] = GetBits(1, 0, 10);
|
553
|
+
}
|
554
|
+
ii++;
|
555
|
+
}
|
556
|
+
i++;
|
557
|
+
}
|
558
|
+
return 0;
|
559
|
+
}
|
560
|
+
|
561
|
+
int UART_file_descriptor = 0;
|
562
|
+
|
563
|
+
int BrickPiSetup(){
|
564
|
+
UART_file_descriptor = serialOpen("/dev/ttyAMA0", 500000);
|
565
|
+
if(UART_file_descriptor == -1){
|
566
|
+
return -1;
|
567
|
+
}
|
568
|
+
return 0;
|
569
|
+
}
|
570
|
+
|
571
|
+
void BrickPiTx(unsigned char dest, unsigned char ByteCount, unsigned char OutArray[]){
|
572
|
+
unsigned char tx_buffer[256];
|
573
|
+
tx_buffer[0] = dest;
|
574
|
+
tx_buffer[1] = dest + ByteCount;
|
575
|
+
tx_buffer[2] = ByteCount;
|
576
|
+
unsigned char i = 0;
|
577
|
+
while(i < ByteCount){
|
578
|
+
tx_buffer[1] += OutArray[i];
|
579
|
+
tx_buffer[i + 3] = OutArray[i];
|
580
|
+
i++;
|
581
|
+
}
|
582
|
+
i = 0;
|
583
|
+
while(i < (ByteCount + 3)){
|
584
|
+
serialPutchar(UART_file_descriptor, tx_buffer[i]);
|
585
|
+
i++;
|
586
|
+
}
|
587
|
+
}
|
588
|
+
|
589
|
+
int BrickPiRx(unsigned char *InBytes, unsigned char *InArray, long timeout){ // timeout in uS, not mS
|
590
|
+
unsigned char rx_buffer[256];
|
591
|
+
unsigned char RxBytes = 0;
|
592
|
+
unsigned char CheckSum = 0;
|
593
|
+
unsigned char i = 0;
|
594
|
+
int result;
|
595
|
+
unsigned long OrigionalTick = CurrentTickUs();
|
596
|
+
while(serialDataAvail(UART_file_descriptor) <= 0){
|
597
|
+
if(timeout && ((CurrentTickUs() - OrigionalTick) >= timeout))return -2;
|
598
|
+
}
|
599
|
+
|
600
|
+
RxBytes = 0;
|
601
|
+
while(RxBytes < serialDataAvail(UART_file_descriptor)){ // If it's been 1 ms since the last data was received, assume it's the end of the message.
|
602
|
+
RxBytes = serialDataAvail(UART_file_descriptor);
|
603
|
+
usleep(75);
|
604
|
+
}
|
605
|
+
|
606
|
+
i = 0;
|
607
|
+
while(i < RxBytes){
|
608
|
+
result = serialGetchar(UART_file_descriptor);
|
609
|
+
if(result >= 0){
|
610
|
+
rx_buffer[i] = result;
|
611
|
+
}
|
612
|
+
else{
|
613
|
+
return -1;
|
614
|
+
}
|
615
|
+
i++;
|
616
|
+
}
|
617
|
+
|
618
|
+
if(RxBytes < 2)
|
619
|
+
return -4;
|
620
|
+
|
621
|
+
if(RxBytes < (rx_buffer[1] + 2))
|
622
|
+
return -6;
|
623
|
+
|
624
|
+
CheckSum = rx_buffer[1];
|
625
|
+
|
626
|
+
i = 0;
|
627
|
+
while(i < (RxBytes - 2)){
|
628
|
+
CheckSum += rx_buffer[i + 2];
|
629
|
+
InArray[i] = rx_buffer[i + 2];
|
630
|
+
i++;
|
631
|
+
}
|
632
|
+
|
633
|
+
if(CheckSum != rx_buffer[0])
|
634
|
+
return -5;
|
635
|
+
|
636
|
+
*InBytes = (RxBytes - 2);
|
637
|
+
|
638
|
+
return 0;
|
639
|
+
}
|
640
|
+
|
641
|
+
#endif
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#include "ruby.h";
|
2
|
+
#include "tick.h";
|
3
|
+
#include "BrickPi.h";
|
4
|
+
|
5
|
+
VALUE bprb_BrickPiSetup(VALUE self) {
|
6
|
+
return INT2FIX(BrickPiSetup());
|
7
|
+
}
|
8
|
+
VALUE bprb_ClearTick(VALUE self) {
|
9
|
+
return INT2FIX(ClearTick());
|
10
|
+
}
|
11
|
+
|
12
|
+
VALUE bprb_MotorSpeed_set(VALUE self, VALUE key, VALUE value) {
|
13
|
+
int index = FIX2INT(key);
|
14
|
+
BrickPi.MotorSpeed[index] = FIX2INT(value);
|
15
|
+
return value;
|
16
|
+
}
|
17
|
+
|
18
|
+
VALUE bprb_Address_set(VALUE self, VALUE key, VALUE value) {
|
19
|
+
int index = FIX2INT(key);
|
20
|
+
BrickPi.Address[index] = FIX2INT(value);
|
21
|
+
return value;
|
22
|
+
}
|
23
|
+
|
24
|
+
VALUE bprb_MotorEnable_set(VALUE self, VALUE key, VALUE value) {
|
25
|
+
int index = FIX2INT(key);
|
26
|
+
BrickPi.MotorEnable[index] = FIX2INT(value);
|
27
|
+
return value;
|
28
|
+
}
|
29
|
+
|
30
|
+
VALUE bprb_Timeout_set(VALUE self, VALUE timeout) {
|
31
|
+
BrickPi.Timeout = FIX2INT(timeout);
|
32
|
+
return timeout;
|
33
|
+
}
|
34
|
+
|
35
|
+
VALUE bprb_BrickPiSetTimeout(VALUE self) {
|
36
|
+
return INT2FIX(BrickPiSetTimeout());
|
37
|
+
}
|
38
|
+
|
39
|
+
VALUE bprb_BrickPiUpdateValues(VALUE self) {
|
40
|
+
return INT2FIX(BrickPiUpdateValues());
|
41
|
+
}
|
42
|
+
|
43
|
+
void Init_native() {
|
44
|
+
VALUE BrickPi = rb_define_module("BrickPi");
|
45
|
+
VALUE Native = rb_define_module_under(BrickPi, "Native");
|
46
|
+
rb_define_singleton_method(Native, "BrickPiSetup", bprb_BrickPiSetup, 0);
|
47
|
+
rb_define_singleton_method(Native, "ClearTick", bprb_ClearTick, 0);
|
48
|
+
VALUE MotorSpeed = rb_define_module_under(Native, "MotorSpeed");
|
49
|
+
rb_define_singleton_method(MotorSpeed, "[]=", bprb_MotorSpeed_set, 2);
|
50
|
+
VALUE MotorEnable = rb_define_module_under(Native, "MotorEnable");
|
51
|
+
rb_define_singleton_method(MotorEnable, "[]=", bprb_MotorEnable_set, 2);
|
52
|
+
VALUE Address = rb_define_module_under(Native, "Address");
|
53
|
+
rb_define_singleton_method(Address, "[]=", bprb_Address_set, 2);
|
54
|
+
rb_define_singleton_method(Native, "Timeout=", bprb_Timeout_set, 1);
|
55
|
+
rb_define_singleton_method(Native, "BrickPiSetTimeout", bprb_BrickPiSetTimeout, 0);
|
56
|
+
rb_define_singleton_method(Native, "BrickPiUpdateValues", bprb_BrickPiUpdateValues, 0);
|
57
|
+
rb_define_const(Native, "PORT_A", INT2FIX(0));
|
58
|
+
rb_define_const(Native, "PORT_B", INT2FIX(1));
|
59
|
+
rb_define_const(Native, "PORT_C", INT2FIX(2));
|
60
|
+
rb_define_const(Native, "PORT_D", INT2FIX(3));
|
61
|
+
rb_define_const(Native, "PORT_1", INT2FIX(0));
|
62
|
+
rb_define_const(Native, "PORT_2", INT2FIX(1));
|
63
|
+
rb_define_const(Native, "PORT_3", INT2FIX(2));
|
64
|
+
rb_define_const(Native, "PORT_4", INT2FIX(3));
|
65
|
+
}
|
data/ext/brick_pi/tick.h
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
/*
|
2
|
+
* Matthew Richardson
|
3
|
+
* matthewrichardson37<at>gmail.com
|
4
|
+
* http://mattallen37.wordpress.com/
|
5
|
+
* Initial date: June 3, 2013
|
6
|
+
* Last updated: June 4, 2013
|
7
|
+
*
|
8
|
+
* You may use this code as you wish, provided you give credit where it's due.
|
9
|
+
*
|
10
|
+
* This is a library of functions for timing.
|
11
|
+
*/
|
12
|
+
|
13
|
+
#ifndef __tick_h_
|
14
|
+
#define __tick_h_
|
15
|
+
|
16
|
+
#include <time.h>
|
17
|
+
|
18
|
+
// gcc -o program test.c -lrt
|
19
|
+
|
20
|
+
struct timespec tick_struct;
|
21
|
+
unsigned long sec_offset = 0;
|
22
|
+
unsigned long nsec_offset = 0;
|
23
|
+
|
24
|
+
int ClearTick(){
|
25
|
+
clock_gettime(CLOCK_REALTIME, &tick_struct);
|
26
|
+
sec_offset = tick_struct.tv_sec;
|
27
|
+
nsec_offset = tick_struct.tv_nsec;
|
28
|
+
}
|
29
|
+
|
30
|
+
unsigned long CurrentTickMs(){
|
31
|
+
clock_gettime(CLOCK_REALTIME, &tick_struct);
|
32
|
+
tick_struct.tv_sec -= sec_offset;
|
33
|
+
tick_struct.tv_nsec -= nsec_offset;
|
34
|
+
tick_struct.tv_nsec /= 1000000;
|
35
|
+
return ((tick_struct.tv_sec * 1000) + tick_struct.tv_nsec);
|
36
|
+
}
|
37
|
+
|
38
|
+
unsigned long CurrentTickUs(){
|
39
|
+
clock_gettime(CLOCK_REALTIME, &tick_struct);
|
40
|
+
tick_struct.tv_sec -= sec_offset;
|
41
|
+
tick_struct.tv_nsec -= nsec_offset;
|
42
|
+
tick_struct.tv_nsec /= 1000;
|
43
|
+
return ((tick_struct.tv_sec * 1000000) + tick_struct.tv_nsec);
|
44
|
+
}
|
45
|
+
|
46
|
+
#endif
|
data/lib/brick_pi.rb
ADDED
data/lib/brick_pi/bot.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'brick_pi'
|
2
|
+
include BrickPi
|
3
|
+
|
4
|
+
module BrickPi
|
5
|
+
class Bot
|
6
|
+
attr_accessor :motor1, :motor2
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
Native.BrickPiSetup()
|
10
|
+
@motor1 = ::BrickPi::Motor.new(Native::PORT_A)
|
11
|
+
@motor2 = ::BrickPi::Motor.new(Native::PORT_B)
|
12
|
+
@motor3 = ::BrickPi::Motor.new(Native::PORT_C)
|
13
|
+
@motor4 = ::BrickPi::Motor.new(Native::PORT_D)
|
14
|
+
Native::Address[0] = 1
|
15
|
+
Native::Address[1] = 2
|
16
|
+
end
|
17
|
+
|
18
|
+
def start
|
19
|
+
@stop = false
|
20
|
+
Native.ClearTick()
|
21
|
+
Native.Timeout = 50
|
22
|
+
Native.BrickPiSetTimeout()
|
23
|
+
|
24
|
+
Thread.new do
|
25
|
+
until @stop do
|
26
|
+
Native.BrickPiUpdateValues()
|
27
|
+
sleep(50/1000)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def stop
|
33
|
+
@stop = true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module BrickPi
|
2
|
+
class Motor
|
3
|
+
def initialize(port)
|
4
|
+
@port = port
|
5
|
+
Native::MotorEnable[@port] = 1
|
6
|
+
end
|
7
|
+
|
8
|
+
def spin(speed)
|
9
|
+
speed = [-100, [100, speed].min].max
|
10
|
+
motor_speed = (speed * 2.55).round
|
11
|
+
puts motor_speed
|
12
|
+
Native::MotorSpeed[@port] = motor_speed
|
13
|
+
end
|
14
|
+
|
15
|
+
def stop
|
16
|
+
spin 0
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: brick-pi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brandon Hays
|
8
|
+
- Charles Lowell
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-04-30 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.6'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.6'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
description: BrickPi uses a C library to communicate with Lego Mindstorms motors and
|
43
|
+
sensors via GPIO on the Raspberry Pi. This library wraps the C and exposes a nicer,
|
44
|
+
object-oriented interface via Ruby.
|
45
|
+
email:
|
46
|
+
- brandon.hays@gmail.com
|
47
|
+
executables: []
|
48
|
+
extensions:
|
49
|
+
- ext/brick_pi/extconf.rb
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- .gitignore
|
53
|
+
- Gemfile
|
54
|
+
- LICENSE
|
55
|
+
- LICENSE.txt
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- brick_pi.gemspec
|
59
|
+
- ext/brick_pi/BrickPi.h
|
60
|
+
- ext/brick_pi/extconf.rb
|
61
|
+
- ext/brick_pi/native.c
|
62
|
+
- ext/brick_pi/tick.h
|
63
|
+
- lib/brick_pi.rb
|
64
|
+
- lib/brick_pi/bot.rb
|
65
|
+
- lib/brick_pi/motor.rb
|
66
|
+
- lib/brick_pi/version.rb
|
67
|
+
homepage: ''
|
68
|
+
licenses:
|
69
|
+
- MIT
|
70
|
+
metadata: {}
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
- ext
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 2.0.3
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: Ruby library to run the BrickPi drivers for Lego Mindstorms
|
92
|
+
test_files: []
|