brick-pi 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|