Arduinoäºææ©+mrubyã§ã©ã¸ã³ã³ãèªåèµ°è¡ãã¦ã¿ã
2014/2/20追è¨
ä¸è¨ã¯RSTRING_PTR()ã誤ã£ã使ãæ¹ããã¦ãã¾ããmrb_valueã«RSTRING_PTR()ãã¯ãã使ã£ãå ´åã«åãåºããæååã¯終端がNULLとは限りませんã®ã§ã注æ
前回ã¾ã§ã§ãchipKIT Max32ä¸ã§mrubyããã°ã©ã ãããããéçºã§ããããã«ãªãã¾ãããä½ããããã¨ã¯ç¡ããã¨èãã¦ãæéãã§ããã©ã¸ã³ã³ã®ã¢ã¼ã¿ã¨ãµã¼ããå¶å¾¡ã§ãããã¨ãããã£ãã®ã§ãèªåèµ°è¡ãã¦ã¿ã¾ããã
æåã«åãæãèµ°è¡ããã®æ¬¡ã¯ï¼ã®åé転ã§ãã
ã»ã»ã»æ®éªå¤ããï¼ã·ã£ãããå¤ãã¦ï¼ã®åã¯æ£ã
(ç¬)
ã©ã¡ããmrubyã®ã³ã¼ãã§å¶å¾¡ãã¦ãã¾ããéªããªãæã«èª¿æ´ããã°ããå°ãã¾ã¨ãã«èµ°ãã¯ãã
åèµ°è¡(circle.rb)
Serial.println("loading circle.rb....") class Circle include Arduino def initialize @servo = Servo.new @servo.attach(5) end def idleloop end def run Serial.println("circle started") delay(5000) @servo.write(60) analogWrite(3, 220) delay(10 * 1000) analogWrite(3, 128) @servo.write(90) delay(1000) end end Circle.new
å «ã®å(eight.rb)
Serial.println("loading eight.rb...") class Eight include Arduino def initialize @servo = Servo.new @servo.attach(5) end def idleloop end def angle(val) @servo.write(val) end def speed(val) ããããã#ã¢ã¼ã¿ã¯3çªPINã«æ¥ç¶ analogWrite(3, val) end #å «ã®åé転 def draw_8 #straight angle 90 speed 240 delay 1000 #turn left angle 0 speed 210 delay 1500 #straight angle 90 speed 240 delay 1000 #turn right angle 180 speed 210 delay 1500 end def run Serial.println("eight started") delay(5000) 3.times do draw_8 end angle 90 speed 128 end end Eight.new
angle()ã¯èµè§ã®èª¿æ´ã§ãã0ã§å·¦ãã£ã±ãã90ã§ä¸å¤®(ç´é²)ã180ã§å³ãã£ã±ãã
speed()ã¯ã¢ã¼ã¿å転ã®èª¿æ´ã§ããæ大255ã§ãã³ã¼ããªã³ã°æã¯å°ãé
ããã¦ãã¾ãã
digitalWrite()ãpinMode()ãServoã¯ã©ã¹çã®ArduinoのAPIã®ãã¡ã使ããã®ã ãmrubyããå¼ã³åºããããã«Cå´ã§é¢æ°ãç¨æãã¦ã¾ã(mrbgemåãããâmruby-arduinoã¨ãã¦mrbgemåãã¾ãããï¼ãã¾ããä»åã¯ã¹ã¤ãããæ¼ããããrun()ãCå´ããå¼ã°ãã¾ãã
ããªãé·ãã§ãããCå´ã®ã³ã¼ããä¸å¿ã
#include <Servo.h> #define CHANGE_HEAP_SIZE(size) __asm__ volatile ("\t.globl _min_heap_size\n\t.equ _min_heap_size, " #size "\n") #include <mrbconf.h> #include <mruby.h> #include <mruby/irep.h> #include <mruby/string.h> #include <mruby/value.h> #include <mruby/dump.h> #include <mruby/data.h> #include <mruby/class.h> //extern const char initialcode[]; mrb_state *mrb; char code[4048]; mrb_value sketchObject; mrb_value mrb_serial_begin(mrb_state *mrb, mrb_value self){ mrb_int speed = 0; int n = mrb_get_args(mrb,"i",&speed); Serial.begin(speed); return mrb_nil_value(); } mrb_value mrb_serial_println(mrb_state *mrb, mrb_value self){ mrb_value s; mrb_get_args(mrb,"S", &s); Serial.println(RSTRING_PTR(s)); return mrb_nil_value(); } void mrb_servo_free(mrb_state *mrb, void *ptr){ delete (Servo *)ptr; } struct mrb_data_type mrb_servo_type = {"Servo", mrb_servo_free}; mrb_value mrb_servo_initialize(mrb_state *mrb, mrb_value self){ Servo *newServo = new Servo(); Serial.println("newServo"); Serial.println((int)newServo); DATA_PTR(self) = newServo; DATA_TYPE(self) = &mrb_servo_type; return self; } mrb_value mrb_servo_attach(mrb_state *mrb, mrb_value self){ Servo *servo = (Servo *)mrb_get_datatype(mrb, self, &mrb_servo_type); mrb_int pin = 0; int n = mrb_get_args(mrb, "i", &pin); servo->attach(pin); return mrb_nil_value(); } mrb_value mrb_servo_write(mrb_state *mrb, mrb_value self){ Servo *servo = (Servo *)mrb_get_datatype(mrb, self, &mrb_servo_type); mrb_int angle = 0; int n = mrb_get_args(mrb, "i", &angle); servo->write(angle); return mrb_nil_value(); } mrb_value mrb_arduino_pinMode(mrb_state *mrb, mrb_value self){ mrb_int pin, mode; int n = mrb_get_args(mrb, "ii", &pin, &mode); pinMode(pin, mode); return mrb_nil_value(); } mrb_value mrb_arduino_digitalWrite(mrb_state *mrb, mrb_value self){ mrb_int pin, value; int n = mrb_get_args(mrb, "ii", &pin, &value); digitalWrite(pin, value); return mrb_nil_value(); } mrb_value mrb_arduino_digitalRead(mrb_state *mrb, mrb_value self){ mrb_int pin; int n = mrb_get_args(mrb, "i", &pin); int val = digitalRead(pin); return mrb_fixnum_value(val); } mrb_value mrb_arduino_analogWrite(mrb_state *mrb, mrb_value self){ mrb_int pin, value; int n = mrb_get_args(mrb, "ii", &pin, &value); analogWrite(pin, value); return mrb_nil_value(); } mrb_value mrb_arduino_analogRead(mrb_state *mrb, mrb_value self){ mrb_int pin; int n = mrb_get_args(mrb, "i", &pin); int val = analogRead(pin); return mrb_fixnum_value(val); } mrb_value mrb_arduino_delay(mrb_state *mrb, mrb_value self){ mrb_int ms; int n = mrb_get_args(mrb, "i", &ms); delay(ms); return mrb_nil_value(); } mrb_value mrb_arduino_millis(mrb_state *mrb, mrb_value self){ return mrb_fixnum_value(millis()); } mrb_value mrb_arduino_map(mrb_state *mrb, mrb_value self){ mrb_int value, fromLow, fromHigh, toLow, toHigh; int n = mrb_get_args(mrb, "iiiii", &value, &fromLow, &fromHigh, &toLow, &toHigh); mrb_int ret = map(value, fromLow, fromHigh, toLow, toHigh); return mrb_fixnum_value(ret); } void init_arduino_library(mrb_state *mrb){ RClass *serialClass = mrb_define_class(mrb, "Serial", mrb->object_class); mrb_define_class_method(mrb, serialClass,"begin",mrb_serial_begin, ARGS_REQ(1)); mrb_define_class_method(mrb, serialClass,"println", mrb_serial_println, ARGS_REQ(1)); RClass *servoClass = mrb_define_class(mrb, "Servo", mrb->object_class); MRB_SET_INSTANCE_TT(servoClass, MRB_TT_DATA); mrb_define_method(mrb, servoClass,"initialize", mrb_servo_initialize, ARGS_NONE()); mrb_define_method(mrb, servoClass,"attach", mrb_servo_attach, ARGS_REQ(1)); mrb_define_method(mrb, servoClass,"write", mrb_servo_write, ARGS_REQ(1)); RClass *arduinoModule = mrb_define_module(mrb, "Arduino"); mrb_define_module_function(mrb, arduinoModule, "pinMode", mrb_arduino_pinMode, ARGS_REQ(2)); mrb_define_module_function(mrb, arduinoModule, "digitalWrite", mrb_arduino_digitalWrite, ARGS_REQ(2)); mrb_define_module_function(mrb, arduinoModule, "digitalRead", mrb_arduino_digitalRead, ARGS_REQ(1)); mrb_define_module_function(mrb, arduinoModule, "analogWrite", mrb_arduino_analogWrite, ARGS_REQ(2)); mrb_define_module_function(mrb, arduinoModule, "analogRead", mrb_arduino_analogRead, ARGS_REQ(1)); mrb_define_module_function(mrb, arduinoModule, "delay", mrb_arduino_delay, ARGS_REQ(1)); mrb_define_module_function(mrb, arduinoModule, "millis", mrb_arduino_millis, ARGS_NONE()); mrb_define_module_function(mrb, arduinoModule, "map", mrb_arduino_map, ARGS_REQ(5)); mrb_define_const(mrb, arduinoModule, "HIGH", mrb_fixnum_value(1)); mrb_define_const(mrb, arduinoModule, "LOW", mrb_fixnum_value(0)); mrb_define_const(mrb, arduinoModule, "INPUT", mrb_fixnum_value(0)); mrb_define_const(mrb, arduinoModule, "OUTPUT", mrb_fixnum_value(1)); mrb_define_const(mrb, arduinoModule, "INPUT_PULLUP", mrb_fixnum_value(2)); } unsigned short receiveNewCode(){ unsigned short lengthH = Serial.read(); while(Serial.available() == 0); unsigned short lengthL = Serial.read(); unsigned short codeLength = (lengthH << 8) | lengthL; //send first ack("!") Serial.write(33); unsigned short readedLen = 0; while(readedLen < codeLength){ for (int i = 0 ; i < 100; i++){ while(Serial.available() == 0); code[readedLen] = Serial.read(); readedLen++; if (readedLen == codeLength) break; } Serial.write(35); } Serial.println("uploaded(from mruby_rc_runner)"); return readedLen; } const int MOTOR_PIN = 3; const int START_PIN = 2; const int SERVO_PIN = 5; const int SPEED_CONTROL_PIN = 0; const int ANGLE_CONTROL_PIN = 1; Servo servo; void setup(){ //the magic code to increase heap size to 100kb // see http://www.chipkit.org/forum/viewtopic.php?f=19&t=1565 CHANGE_HEAP_SIZE(100*1024); Serial.begin(9600); pinMode(START_PIN, INPUT); pinMode(MOTOR_PIN, OUTPUT); analogWrite(MOTOR_PIN, 128); mrb = NULL; } void loop(){ if (Serial.available() > 0 ){ /* upload mode */ if (unsigned short codeLen = receiveNewCode()){ if (mrb) mrb_close(mrb); mrb = mrb_open(); init_arduino_library(mrb); FILE *fp = fmemopen(code, codeLen, "rb"); //open buffer as FILE stream. platform dependent. sketchObject = mrb_load_irep_file(mrb, fp); //mrb_value result = mrb_funcall(mrb, sketchObject, "setup", 0); if (mrb->exc){ Serial.println("exception occured in setup on new code"); } } }else if (digitalRead(START_PIN)){ if (!mrb) return; mrb_value result = mrb_funcall(mrb, sketchObject, "run", 0); if (mrb->exc){ Serial.println("exception occured in run"); } }else{ if (mrb) { mrb_value result = mrb_funcall(mrb, sketchObject, "idleloop", 0); if (mrb->exc){ Serial.println("exception occured in idle loop"); } } Serial.println("idle loop"); int speed = analogRead(SPEED_CONTROL_PIN); speed /= 4; if (speed > 127){ if (speed > 250){ speed = 250; } } else if (speed > 64){ //backward slow speed = 2; }else{ //backward fast speed = 1; } analogWrite(MOTOR_PIN, speed); int angle = analogRead(ANGLE_CONTROL_PIN); angle = map(angle, 0, 1024, 180, 0); /*servo.attach(SERVO_PIN); servo.write(angle); delay(500); servo.detach(); */ delay(100); } }