smalrubot 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.
@@ -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