smalrubot 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module Smalrubot
2
+ class BoardNotFound < Exception; end
3
+ end
@@ -0,0 +1,9 @@
1
+ module Smalrubot
2
+ module Components
3
+ require 'smalrubot/components/base_component'
4
+ autoload :Led, 'smalrubot/components/led'
5
+ autoload :Button, 'smalrubot/components/button'
6
+ autoload :Sensor, 'smalrubot/components/sensor'
7
+ autoload :Servo, 'smalrubot/components/servo'
8
+ end
9
+ end
@@ -0,0 +1,44 @@
1
+ module Smalrubot
2
+ module Components
3
+ class BaseComponent
4
+ attr_reader :board, :pin, :pullup
5
+ alias :pins :pin
6
+
7
+ def initialize(options={})
8
+ self.board = options[:board]
9
+ self.pin = options[:pin] || options[:pins]
10
+ self.pullup = options[:pullup]
11
+
12
+ raise 'board and pin or pins are required for a component' if self.board.nil? || self.pin.nil?
13
+ after_initialize(options)
14
+ end
15
+
16
+ #
17
+ # As BaseComponent does a lot of work for you with regarding to setting up, it is
18
+ # best not to override #initialize and instead define an #after_initialize method
19
+ # within your subclass.
20
+ #
21
+ # @note This method should be implemented in the BaseComponent subclass.
22
+ #
23
+ def after_initialize(options={}) ; end
24
+
25
+ protected
26
+
27
+ attr_writer :board, :pin, :pullup
28
+ alias :pins= :pin=
29
+
30
+ def digital_write(pin=self.pin, value)
31
+ self.board.digital_write(pin, value)
32
+ end
33
+
34
+ def analog_write(pin=self.pin, value)
35
+ self.board.analog_write(pin, value)
36
+ end
37
+
38
+ def set_pin_mode(pin=self.pin, mode)
39
+ self.board.set_pin_mode(pin, mode, pullup)
40
+ end
41
+ end
42
+ end
43
+ end
44
+
@@ -0,0 +1,18 @@
1
+ module Smalrubot
2
+ module Components
3
+ class Led < BaseComponent
4
+ def after_initialize(options={})
5
+ set_pin_mode(:out)
6
+ off
7
+ end
8
+
9
+ def on
10
+ digital_write(Board::HIGH)
11
+ end
12
+
13
+ def off
14
+ digital_write(Board::LOW)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ module Smalrubot
2
+ module Components
3
+ class Servo < BaseComponent
4
+ attr_reader :position
5
+
6
+ def after_initialize(options={})
7
+ set_pin_mode(:out)
8
+ board.servo_toggle(pin, 1)
9
+ self.position = options[:position] || 0
10
+ end
11
+
12
+ def position=(value)
13
+ board.servo_write(pin, @position = angle(value))
14
+ end
15
+
16
+ def angle(value)
17
+ value == 180 ? value : value % 180
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,10 @@
1
+ module Smalrubot
2
+ module TxRx
3
+ require 'smalrubot/tx_rx/base'
4
+ require 'smalrubot/tx_rx/serial'
5
+
6
+ def self.new(options={})
7
+ self::Serial.new(options)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,54 @@
1
+ require 'observer'
2
+ require 'timeout'
3
+
4
+ module Smalrubot
5
+ module TxRx
6
+ class Base
7
+ def read(timeout = 0.005)
8
+ line = gets(timeout)
9
+ if line && line.match(/\A\d+:/)
10
+ pin, message = line.chomp.split(/:/)
11
+ if pin && message
12
+ return pin, message
13
+ end
14
+ end
15
+ end
16
+
17
+ def write(message)
18
+ n = io.write(message)
19
+ Smalrubot.debug_log('write: %s(A:%d, E:%d)', message, n, message.length)
20
+ if n != message.length
21
+ raise "FATAL: n(#{n}) != message.length(#{message.length})"
22
+ end
23
+ end
24
+
25
+ def handshake
26
+ 5.times do
27
+ write("!9000000.")
28
+ line = gets(1)
29
+ if line && line.match(/ACK:/)
30
+ flush_read
31
+ return line.chomp.split(/:/)[1].to_i
32
+ end
33
+ end
34
+ raise BoardNotFound
35
+ end
36
+
37
+ def flush_read
38
+ gets until gets == nil
39
+ end
40
+
41
+ RETURN_CODE = "\n".ord
42
+
43
+ def gets(timeout=0.005)
44
+ Timeout.timeout(timeout) do
45
+ s = io.gets
46
+ Smalrubot.debug_log("gets: %s", s)
47
+ return s
48
+ end
49
+ rescue Exception
50
+ nil
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,70 @@
1
+ require 'rubyserial'
2
+
3
+ module Smalrubot
4
+ module TxRx
5
+ class Serial < Base
6
+ BAUD = 115200
7
+
8
+ def initialize(options={})
9
+ @device = options[:device]
10
+ @baud = options[:baud] || BAUD
11
+ @first_write = true
12
+ end
13
+
14
+ def io
15
+ @io ||= connect
16
+ end
17
+
18
+ def handshake
19
+ while tty_devices.length > 0
20
+ begin
21
+ if on_windows?
22
+ io; sleep 3
23
+ end
24
+
25
+ return super
26
+ rescue BoardNotFound
27
+ @tty_devices.shift
28
+ @io.close
29
+ @io = nil
30
+ end
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def connect
37
+ tty_devices.dup.each do |device|
38
+ begin
39
+ serial = ::Serial.new(device, @baud)
40
+ Smalrubot.debug_log('found board: %s (%d)', device, @baud)
41
+ return serial
42
+ rescue Exception
43
+ @tty_devices.shift
44
+ Smalrubot.debug_log('could not access: %s', device)
45
+ Smalrubot.show_backtrace($!)
46
+ end
47
+ end
48
+ raise BoardNotFound
49
+ end
50
+
51
+ def tty_devices
52
+ if !@tty_devices
53
+ if @device
54
+ @tty_devices = [@device]
55
+ elsif on_windows?
56
+ @tty_devices = (1..256).map { |n| "COM#{n}" }
57
+ else
58
+ @tty_devices =
59
+ `ls /dev`.split("\n").grep(/usb|ACM/i).map{ |d| "/dev/#{d}" }
60
+ end
61
+ end
62
+ @tty_devices
63
+ end
64
+
65
+ def on_windows?
66
+ RUBY_PLATFORM.match /mswin|mingw/i
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,3 @@
1
+ module Smalrubot
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,158 @@
1
+ /*
2
+ Library for smalrubot ruby gem.
3
+ */
4
+
5
+ #include "Arduino.h"
6
+ #include "Smalrubot.h"
7
+
8
+ Smalrubot::Smalrubot(){
9
+ reset();
10
+ }
11
+
12
+ void Smalrubot::parse(char c) {
13
+ if (c == '!') index = 0; // Reset request
14
+ else if (c == '.') process(); // End request and process
15
+ else request[index++] = c; // Append to request
16
+ }
17
+
18
+ void Smalrubot::process() {
19
+ response[0] = '\0';
20
+
21
+ // Parse the request.
22
+ strncpy(cmdStr, request, 2); cmdStr[2] = '\0';
23
+ strncpy(pinStr, request + 2, 2); pinStr[2] = '\0';
24
+ strncpy(valStr, request + 4, 3); valStr[3] = '\0';
25
+ cmd = atoi(cmdStr);
26
+ pin = atoi(pinStr);
27
+ val = atoi(valStr);
28
+
29
+ #ifdef debug
30
+ Serial.print("Received request - "); Serial.println(request);
31
+ Serial.print("Command - "); Serial.println(cmdStr);
32
+ Serial.print("Pin - "); Serial.println(pinStr);
33
+ Serial.print("Value - "); Serial.println(valStr);
34
+ #endif
35
+
36
+ // Call the command.
37
+ switch(cmd) {
38
+ case 0: setMode (); break;
39
+ case 1: dWrite (); break;
40
+ case 2: dRead (); break;
41
+ case 3: aWrite (); break;
42
+ case 4: aRead (); break;
43
+ case 8: servoToggle (); break;
44
+ case 9: servoWrite (); break;
45
+ case 90: reset (); break;
46
+ default: break;
47
+ }
48
+
49
+ // Write the response.
50
+ if (response[0] != '\0') writeResponse();
51
+
52
+ #ifdef debug
53
+ Serial.print("Responded with - "); Serial.println(response);
54
+ Serial.println();
55
+ #endif
56
+ }
57
+
58
+
59
+
60
+ // WRITE CALLBACK
61
+ void Smalrubot::setupWrite(void (*writeCallback)(char *str)) {
62
+ _writeCallback = writeCallback;
63
+ }
64
+ void Smalrubot::writeResponse() {
65
+ _writeCallback(response);
66
+ }
67
+
68
+
69
+
70
+
71
+
72
+
73
+ // API FUNCTIONS
74
+ // CMD = 00 // Pin Mode
75
+ void Smalrubot::setMode() {
76
+ if (val == 0) {
77
+ pinMode(pin, OUTPUT);
78
+ #ifdef debug
79
+ Serial.print("Set pin "); Serial.print(pin); Serial.print(" to "); Serial.println("OUTPUT mode");
80
+ #endif
81
+ }
82
+ else {
83
+ pinMode(pin, INPUT);
84
+ #ifdef debug
85
+ Serial.print("Set pin "); Serial.print(pin); Serial.print(" to "); Serial.println("INPTUT mode");
86
+ #endif
87
+ }
88
+ }
89
+
90
+ // CMD = 01 // Digital Write
91
+ void Smalrubot::dWrite() {
92
+ if (val == 0) {
93
+ digitalWrite(pin, LOW);
94
+ #ifdef debug
95
+ Serial.print("Digital write "); Serial.print(LOW); Serial.print(" to pin "); Serial.println(pin);
96
+ #endif
97
+ }
98
+ else {
99
+ digitalWrite(pin, HIGH);
100
+ #ifdef debug
101
+ Serial.print("Digital write "); Serial.print(HIGH); Serial.print(" to pin "); Serial.println(pin);
102
+ #endif
103
+ }
104
+ }
105
+
106
+ // CMD = 02 // Digital Read
107
+ void Smalrubot::dRead() {
108
+ rval = digitalRead(pin);
109
+ sprintf(response, "%02d:%02d", pin, rval);
110
+ }
111
+
112
+ // CMD = 03 // Analog (PWM) Write
113
+ void Smalrubot::aWrite() {
114
+ analogWrite(pin,val);
115
+ #ifdef debug
116
+ Serial.print("Analog write "); Serial.print(val); Serial.print(" to pin "); Serial.println(pin);
117
+ #endif
118
+ }
119
+
120
+ // CMD = 04 // Analog Read
121
+ void Smalrubot::aRead() {
122
+ rval = analogRead(pin);
123
+ sprintf(response, "%02d:%02d", pin, rval);
124
+ }
125
+
126
+ // CMD = 08
127
+ // Attach the servo object to pin or detach it.
128
+ void Smalrubot::servoToggle() {
129
+ if (val == 0) {
130
+ #ifdef debug
131
+ Serial.print("Detaching servo"); Serial.print(" on pin "); Serial.println(pin);
132
+ #endif
133
+ servos[pin - SERVO_OFFSET].detach();
134
+ }
135
+ else {
136
+ #ifdef debug
137
+ Serial.print("Attaching servo"); Serial.print(" on pin "); Serial.println(pin);
138
+ #endif
139
+ servos[pin - SERVO_OFFSET].attach(pin);
140
+ }
141
+ }
142
+
143
+ // CMD = 09
144
+ // Write a value to the servo object.
145
+ void Smalrubot::servoWrite() {
146
+ #ifdef debug
147
+ Serial.print("Servo write "); Serial.print(val); Serial.print(" to pin "); Serial.println(pin);
148
+ #endif
149
+ servos[pin - SERVO_OFFSET].write(val);
150
+ }
151
+
152
+ // CMD = 90
153
+ void Smalrubot::reset() {
154
+ #ifdef debug
155
+ Serial.println("Reset the board to defaults.");
156
+ #endif
157
+ sprintf(response, "ACK:%02d", A0);
158
+ }
@@ -0,0 +1,60 @@
1
+ /*
2
+ Library for smalrubot ruby gem.
3
+ */
4
+
5
+ #ifndef Smalrubot_h
6
+ #define Smalrubot_h
7
+
8
+ #include "Arduino.h"
9
+ #include <Servo.h>
10
+
11
+ // Allocate listener storage based on what board we're running.
12
+ #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
13
+ # define PIN_COUNT 70
14
+ # define SERVO_OFFSET 22
15
+ #else
16
+ # define PIN_COUNT 22
17
+ # define SERVO_OFFSET 2
18
+ #endif
19
+
20
+ // Uncomment this line to enable debugging mode.
21
+ // #define debug true
22
+
23
+ class Smalrubot {
24
+ public:
25
+ Smalrubot();
26
+ void setupWrite(void (*writeCallback)(char *str));
27
+ void parse(char c);
28
+ void process();
29
+
30
+ private:
31
+ // Request storage.
32
+ char request[8];
33
+ int index;
34
+ char cmdStr[3];
35
+ byte cmd;
36
+ char pinStr[3];
37
+ byte pin;
38
+ char valStr[4];
39
+ int val;
40
+
41
+ // Value and response storage.
42
+ int rval;
43
+ char response[8];
44
+ void (*_writeCallback)(char *str);
45
+ void writeResponse();
46
+
47
+ Servo servos[12];
48
+
49
+ // API-accessible functions.
50
+ void setMode ();
51
+ void dWrite ();
52
+ void dRead ();
53
+ void aWrite ();
54
+ void aRead ();
55
+ void servoToggle ();
56
+ void servoWrite ();
57
+ void reset ();
58
+ };
59
+
60
+ #endif