austinbv / dino

Dino is a ruby gem that helps you bootstrap prototyping with an Arduino
MIT License
388 stars 84 forks source link

Using dino over bluetooth with Seeed Bluetooth Shield? #78

Closed ghost closed 6 years ago

ghost commented 9 years ago

Hi.

Has anyone figured out how to use dino using Seeed Bluetooth Shield?

I tried replacing dino setup() function with

void setup() {
    Serial.begin(38400);                           // Set BluetoothBee BaudRate to default baud rate 38400
    Serial.print("\r\n+STWMOD=0\r\n");             // set the bluetooth work in slave mode
    Serial.print("\r\n+STNA=SeeedBTSlave\r\n");    // set the bluetooth name as "SeeedBTSlave"
    Serial.print("\r\n+STOAUT=1\r\n");             // Permit Paired device to connect me
    Serial.print("\r\n+STAUTO=1\r\n");             // Auto-connection should be forbidden here
    delay(2000);                                   // This delay is required.
    Serial.print("\r\n+INQ=1\r\n");                // make the slave bluetooth inquirable
    delay(2000);                                   // This delay is required.
    Serial.flush();
    dino.setupWrite(writeCallback);
}

Here is my ruby script.

    board = Dino::Board.new(Dino::TxRx::Serial.new({device: "/dev/cu.SeeedBTSlave-DevB", baud: 38400}))
    led = Dino::Components::Led.new(pin: 8, board: board)
    led.on

I can pair the Arduino with Mac OS X but I keep getting "Board not found" error.

vickash commented 9 years ago

Which branch are you working off?

ghost commented 9 years ago

I am working off master branch

vickash commented 9 years ago

This is more likely a problem in the handshake method than your Bluetooth implementation, which looks correct.

Before doing anything else, try using a terminal application, like CoolTerm: http://freeware.the-meiers.org/. Let it connect to the same device, with the same baud rate, and send it the following line:

!9000000.

If it responds with a line in the format ACK:NN, then we can at least be sure the Bluetooth link is working properly.

From there, here are a couple more things you can try to isolate the problem:

1) Replace the 1 in this line with something like 8: https://github.com/austinbv/dino/blob/master/lib/dino/tx_rx/base.rb#L3

Your code delays 4 seconds total to initialize the BT hardware, so maybe the handshake is being too aggressive and finishes all the retries early, raising the error.

2) If that fails, temporarily replace the entire handshake method in that link so it just returns an integer corresponding to the first analog pin on your board:

"14" if using an UNO "18" if using a Leonardo "54" if using a Mega

This disables the handshake (which usually confirms that the physical board is responding), but still gives the Board class the value it needs to initialize.

Now you need to add at least an 8 second sleep before led.on to give the BT time to initialize. If the led turns on, then we can confirm it's a problem in the handshake method.

What board and OS are you using btw?

ghost commented 9 years ago

I am using Arduino Uno R3 with Mac OS X 10.9.4

This is my new du.ino file:

#include "Dino.h"
#include <Servo.h>
Dino dino;

#include <SoftwareSerial.h>   //Software Serial Port
#define BT_RX         6
#define BT_TX         5
SoftwareSerial        blueToothSerial(BT_RX, BT_TX);

// Dino.h doesn't handle TXRX. Setup a function to tell it to write to blueToothSerial.
void writeResponse(char *response) { blueToothSerial.print(response); blueToothSerial.print("\n"); }
void (*writeCallback)(char *str) = writeResponse;

void setup() {  
  pinMode(BT_RX, INPUT);
  pinMode(BT_TX, OUTPUT);
  blueToothSerial.begin(9600);                          // Set BluetoothBee BaudRate to default baud rate 38400
  blueToothSerial.print("\r\n+STBD=9600\r\n");
  blueToothSerial.print("\r\n+STWMOD=0\r\n");             // set the bluetooth work in slave mode
  blueToothSerial.print("\r\n+STNA=SeeedBTSlave\r\n");    // set the bluetooth name as "SeeedBTSlave"
  blueToothSerial.print("\r\n+STOAUT=1\r\n");             // Permit Paired device to connect me
  blueToothSerial.print("\r\n+STAUTO=1\r\n");             // Auto-connection should be forbidden here
  blueToothSerial.print("\r\n+DLPIN\r\n"); // delete pin code
  delay(4000);                                            // This delay is required.
  blueToothSerial.print("\r\n+INQ=1\r\n");                // make the slave bluetooth inquirable
  Serial.println("The slave bluetooth is inquirable!");
  delay(4000);                                            // This delay is required.
  blueToothSerial.flush();

  dino.setupWrite(writeCallback);
}

void loop() {
  while(blueToothSerial.available() > 0) dino.parse(blueToothSerial.read());
  dino.updateListeners();
  blueToothSerial.flush();
}

I replaced all 'Serial' on Dino.cpp with 'blueToothSerial'

Now that I execute:

  cat /dev/cu.SeeedBTSlave-DevB

Once it printed out:

  ACK:14

And then, nothing.

When I reset the board it prints out:

+STBD=9600

+STWMOD=0

+STNA=SeeedBTSlave

+STOAUT=1

+STAUTO=1

+DLPIN

+INQ=1

Edit: It prints out

ACK:14

when I send

!9000000.

I just forgot the '.' character

ghost commented 9 years ago

It is finally working.

Here is my temporary monkey patch:

require 'observer' require 'timeout'

module Dino
  module TxRx
    class Base
      include Observable

      def read
        @thread ||= Thread.new do
          loop do
            line = gets
            if line && line.match(/\A\d+:/)
              pin, message = line.chop.split(/:/)
              pin && message && changed && notify_observers(pin, message)
            end
          end
        end
      end

      def close_read
        return nil if @thread.nil?
        Thread.kill(@thread)
        @thread = nil
      end

      def write(message)
        loop do
          if IO.select(nil, [io], nil)
            puts message # debug
            20.times do # spray and pray
              io.syswrite(message)
              sleep 0.01
            end
            break
          end
        end
      end

      def handshake
        #return 14
        loop do
          write("!9000000.")
          line = gets(0.25)
          if line && line.match(/ACK:/)
            flush_read
            puts line
            return line.chop.split(/:/)[1].to_i
          end
        end
        raise BoardNotFound
      end

      def flush_read
        gets until gets == nil
      end

      def gets(timeout=0.005)
        IO.select([io], nil, nil, timeout) && io.gets
      end
    end
  end
end

Recommended baud rate: 38400

And this is my new du.ino file:

#include "Dino.h"
#include <Servo.h>
Dino dino;

#define debug 1

#include <SoftwareSerial.h>   //Software Serial Port
#define RxD         6
#define TxD         5
SoftwareSerial      blueToothSerial(RxD,TxD);

// Dino.h doesn't handle TXRX. Setup a function to tell it to write to blueToothSerial.
void writeResponse(char *response) { blueToothSerial.print(response); blueToothSerial.print("\n"); }
void (*writeCallback)(char *str) = writeResponse;

void setup() {
  Serial.begin(9600);
  pinMode(RxD, INPUT);
  pinMode(TxD, OUTPUT);

  blueToothSerial.begin(38400);                            // Set BluetoothBee BaudRate to default baud rate 38400
  blueToothSerial.print("\r\n+STBD=38400\r\n");           // set the bluetooth work in slave mode

  blueToothSerial.print("\r\n+STWMOD=0\r\n");             // set the bluetooth work in slave mode
  blueToothSerial.print("\r\n+STNA=SeeedBTSlave\r\n");    // set the bluetooth name as "SeeedBTSlave"
  blueToothSerial.print("\r\n+STOAUT=1\r\n");             // Permit Paired device to connect me
  blueToothSerial.print("\r\n+STAUTO=0\r\n");             // Auto-connection should be forbidden here
  delay(4000);                                            // This delay is required.
  blueToothSerial.print("\r\n+INQ=1\r\n");                // make the slave bluetooth inquirable
  #ifdef debug
    Serial.println("The slave bluetooth is inquirable!");
  #endif
  delay(4000);                                            // This delay is required.
  blueToothSerial.flush();

  dino.setupWrite(writeCallback);
}

void loop() {
  while(blueToothSerial.available() > 0) dino.parse(blueToothSerial.read());
  dino.updateListeners();
  blueToothSerial.flush();
}