PitMotor V2
PitMotor è un piccolo rover controllato da Arduino e comandato da Processing attraverso USB o Bluetooth.
I movimenti sono dati da due motori che vengono controllati attaverso l'integrato LM293D.
In questo video si vede il controllo completo tramite Android - che invia i dati a Arduino attraverso Bluetoorh.
Cosa serve:
- Arduino
- Led
- Rover
- LM293D
- Scheda Pit HC-05 con Modulo HC-05;
- Smartophone Android;
- Processing installato sul PC
- PC
Preparativi (come in PitBraccio):
- Installare Processing completo del Mode Android (vedasi l'interessantissima e completa guida "Sviluppare app con Processing" a cura dell’ing. MIRCO SEGATELLO - su Elettronica IN fine 2015 - Inizio 2016)
In questo secondo video si vede il robottino comandato via seriale da Processing su PC
Software lato Processing:
- PitMotor è stato elaborato modificando l'esempio BluetoothCursors - Ketai Library for Android: http://KetaiProject.org di Daniel Sauter
- Sono state implementate delle routine per il controllo di arduino - si è in particolare creata una piccola libreria (UI_PitButtonSliderLib) che contiene tre oggetti Pulsante (Button), interruttore (Switch), cursore (Slider), pad (JOY01) per il controllo dei motori
Software lato Arduino:
- Sul lato Arduino è un programma molto semplice in quanto si tratta di deggere da seriale i comandi e di inviarli alle rispettive porte. I comandi vengono passati tramite seriale nel formato PitProto.
- Il protocollo utilizzato rappresenta il comandi ad Arduino attraverso stringhe nella forma 1 3 4 (0 000 0000);
- il primo carattere di controllo (CTR - HEADER) identifica che si stà passando un comando (nel nostro caso la lettera "Z" - si puo scegliere evidentemente qualsiasi carattere che normalmente non viene utilizzato nella comunicazione);
- i tre caratteri successivi costituiscono l'ID del componenti - nel nostro caso:
- VDX (Valore da assegnare al Motore Destro);
- MSN (Valore da assegnare al Motore Sinistro);
- SDX (Stato del motore destro);
- SSN (Stato del motore sinistro);
- i quattro caratteri successivi costituiscono il dato/parametro (nel nostro caso 0000 o 0001 per identificare lo stato dei motori - acceso/spento, 0000 - 0999 - il valore del motore --> valre reale = valore - 500 < se maggiore di zero motore avanti se minore di zero allora indietro>);
- Attenzione ogni volta che viene identificato il codice di controlllo (CTR) Arduino legge sempre 7 caratteri dalla seriale e quindi come si vede ad esempio per i led per passare lo stato 0/1 si usa una stringa di 4 caratteri 0000/0001. Volendo questa parte puo essere resa più funzionale ma per il nostro scopo funziona egregiamente anche così.
Circuito ed elettronica:
- Motori sono alimentati separatamante attraverso le batteria posizionate sotto il PitMotor. Arduino nella versione da tavolo è alimentato tramite cavo USB collegato al PC, nella vesione da terra è alimentato tramite batteria a 9V.
Finalmente in azione:
Download:
- PitMotor V2 - Sketch Arduino Processing e schemi Fritzing --> PC via Seriale
- PitMotor V2 - Sketch Arduino Processing e schemi Fritzing --> Android via Bluetooth
Codice sorgente Arduino:
/*
PitMotor V2 - Rev 20
Versione V2 - ZappocoS 2/2017
www.zappoco.altervista.org
- Scheda HC-04 con PitBt HC05
- codice PIN per accoppiamento BT 1234
- LM293D
- due motori
- led cavetti ecc
-
*/
// motore destro (1)
// Arduino L293D
// | |
const int enable1Pin = 2; // 7; // porta digitale per il pin 1 (1,2EN)
const int motor1Pin = 8; // 8; // porta digitale per il pin 2 (1A) --> direzione della rotazione
const int motor2Pin = 9; // 9; // porta digitale (PWM) per il pin 7 (2A) --> velocità della rotazione
// motore sinistro (2)
const int enable2Pin = 4; // 4; // porta digitale per il pin 9 (3,4EN)
const int motor3Pin = 7; // 2; // porta digitale per il pin 10 (3A) --> direzione della rotazione
const int motor4Pin = 6; // 5; // porta digitale (PWM) per il pin 15 (4A) --> velocità della rotazione
// velocità dei motori
int spdMDex, spdMSin;
int mSinSts = 0;
int mDexSts = 0;
int spdMDmy;
int dirMDex = HIGH;
int dirMSin = HIGH;
// --------------------------------
// ARDUINO ! HC-05 ! CAVO
// 1 (10) TX ! RX ! giallo (con resistenze 1 KOhm)
// 0 (11) RX ! TX ! blu
//
// --------------------------------
// Protocollo comando (PitProto)
//
// D
// C A
// T I T
// R D O
//
// 0 000 0000
// --------------------------------
char CT_PitProto = 'Z';
String ID_PitProto;
String DT_PitProto;
String StrDummy = "12345";
String CodCM;
int IntCM;
int ServoMin = 25;
char val;
boolean flagDebug = false;
void setup()
{
// motore 1
pinMode(enable1Pin, OUTPUT);
pinMode(motor1Pin, OUTPUT);
pinMode(motor2Pin, OUTPUT);
// motore 2
pinMode(enable2Pin, OUTPUT);
pinMode(motor3Pin, OUTPUT);
pinMode(motor4Pin, OUTPUT);
pinMode(12, OUTPUT);
pinMode(12, OUTPUT);
Serial.begin (9600);
}
void loop()
{
if (flagDebug)
{
//Motore 1 avanti
digitalWrite(enable1Pin, HIGH);
digitalWrite(motor1Pin, LOW);
digitalWrite(12, HIGH);
analogWrite(motor2Pin, 255);
delay (1000);
digitalWrite(enable1Pin, LOW);
delay (1000);
//Motore 1 indietro
digitalWrite(enable1Pin, HIGH);
digitalWrite(motor1Pin, HIGH);
digitalWrite(12, LOW);
analogWrite(motor2Pin, 0);
delay (1000);
digitalWrite(enable1Pin, LOW);
delay (1000);
//Motore 2 avanti
digitalWrite(enable2Pin, HIGH);
digitalWrite(motor3Pin, LOW);
digitalWrite(13, HIGH);
analogWrite(motor4Pin, 255);
delay (1000);
digitalWrite(enable2Pin, LOW);
delay (1000);
//Motore 2 indietro
digitalWrite(enable2Pin, HIGH);
digitalWrite(motor3Pin, HIGH);
digitalWrite(13, LOW);
analogWrite(motor4Pin, 0);
delay (1000);
digitalWrite(enable2Pin, LOW);
delay (1000);
//Motore 1 2 avanti
digitalWrite(enable1Pin, HIGH);
digitalWrite(motor1Pin, LOW);
analogWrite(motor2Pin, 255);
digitalWrite(enable2Pin, HIGH);
digitalWrite(motor3Pin, LOW);
analogWrite(motor4Pin, 255);
delay (1000);
digitalWrite(enable1Pin, LOW);
digitalWrite(enable2Pin, LOW);
delay (1000);
//Motore 1 2 indietro
digitalWrite(enable1Pin, HIGH);
digitalWrite(motor1Pin, HIGH);
analogWrite(motor2Pin, 0);
digitalWrite(enable2Pin, HIGH);
digitalWrite(motor3Pin, HIGH);
analogWrite(motor4Pin, 0);
delay (1000);
digitalWrite(enable1Pin, LOW);
digitalWrite(enable2Pin, LOW);
delay (1000);
}
else
{
// ---------------------------------------------------------------
// lettura della seriale secondo il protocollo PitProto
// se viene inviato un carattere 'Z' --> Start
// viene letta la stringa successiva
// secondo il protocollo 1 3 4
// ---------------------------------------------------------------
ReadPitProtoCMD();
IntCM = DT_PitProto.toInt();
//Velocità Motore destro
if (ID_PitProto == "VDX" && spdMDex != IntCM)
{
spdMDex = IntCM - 500;
spdMDmy = abs(IntCM - 500);
if (spdMDex >= 0)
{
digitalWrite(12, HIGH);
dirMDex = LOW;
spdMDmy = spdMDmy;
}
else
{
digitalWrite(12, LOW);
dirMDex = HIGH;
spdMDmy = 255 - spdMDmy;
}
//Motore 1
digitalWrite(motor1Pin, dirMDex);
analogWrite(motor2Pin, spdMDmy);
}
//Velocità Motore sinistro
if (ID_PitProto == "VSN" && spdMSin != IntCM)
{
spdMSin = IntCM - 500;
spdMDmy = abs(IntCM - 500);
if (spdMSin >= 0)
{
digitalWrite(13, HIGH);
dirMSin = LOW;
spdMDmy = spdMDmy;
}
else
{
digitalWrite(13, LOW);
dirMSin = HIGH;
spdMDmy = 255 - spdMDmy;
}
digitalWrite(motor3Pin, dirMSin);
analogWrite(motor4Pin, spdMDmy);
}
//Status Motore destro
if (ID_PitProto == "SDX" && mDexSts != IntCM)
{
mDexSts = abs(IntCM);
if(mDexSts == 1)
{
digitalWrite(enable1Pin, HIGH);
}
else if( IntCM == 0)
{
digitalWrite(enable1Pin, LOW);
}
digitalWrite(motor1Pin, LOW);
analogWrite(motor2Pin, 0);
delay (30);
}
//Status Motore Sinistro
if (ID_PitProto == "SSN" && mSinSts != IntCM)
{
mSinSts = abs(IntCM);
if(mSinSts == 1)
{
digitalWrite(enable2Pin, HIGH);
}
if( IntCM == 0)
{
digitalWrite(enable2Pin, LOW);
}
digitalWrite(motor3Pin, LOW);
analogWrite(motor4Pin, 0);
delay (30);
}
}
}
String ItoS (int ii, int nn)
{
String gg;
int ll;
gg.concat(ii);
gg = " " + gg;
ll = gg.length();
gg = gg.substring(ll - nn,ll);
return gg;
}
void ReadPitProtoCMD ()
{
if(Serial.available() > 0)
{
char CDummy;
CDummy = Serial.read();
val = CDummy;
Serial.print (CDummy);
if (CDummy == CT_PitProto)
{
ID_PitProto = "";
int i = 0;
//delay (10);
while (i <= 2)
{
if(Serial.available() > 0)
{
CDummy = Serial.read();
//if(Serial.available() > 0)
//{
ID_PitProto += CDummy;
i++;
//}
}
}
DT_PitProto = "";
i = 0;
delay (10);
while (i <= 3)
{
if(Serial.available() > 0)
{
CDummy = Serial.read();
//if (isAlphaNumeric(CDummy))
//{
DT_PitProto += CDummy;
i++;
//}
}
}
//Serial.println ( "ID_PitProto : " + ID_PitProto );
//Serial.println ( "DT_PitProto : " + DT_PitProto );
}
}
}
/*
void DeCodeBT (String S)
{
String Cod000;
Cod000 = S.substring(2,5);
CodCM = S.substring(0,2);
IntCM = Cod000.toInt();
}
*/
Codice sorgente Processing:
/*
Pit Motor V2 rev 01
ZappocoS 2/2017
www.zappoco.altervista.org
Svilluppato partendo da BluetoothCursors esempio della libreria Ketai
* <p>Ketai Library for Android: http://KetaiProject.org</p>
* <p>Updated: 2012-05-18 Daniel Sauter/j.duran</p>
*/
/* Solo per Android inizio
//required for BT enabling on startup
import android.content.Intent;
import android.os.Bundle;
Solo per Android fine */
import ketai.net.bluetooth.*;
import ketai.ui.*;
import ketai.net.*;
import oscP5.*;
// /* Solo per Windows
import processing.serial.*;
Serial port; // Definisce il nome della porta seriale su cui scrivere
// Solo per Windows */
// public boolean Arduino = true; //impostare a true per utilizzare arduino via seriale
public boolean Android; // serve per spostare le scritte nel caso di interfaccia Bluethoot
public boolean flagDeb = true; //impostare a true per utilizzare arduino via seriale
//font
PFont Font1;
// stato dei led
boolean onMtrSin = false;
boolean oldonMtrSin = true;
boolean mRSTLed = true;
boolean oldmRSTLed = false;
boolean mEQULed = false;
boolean oldmEQULed = false;
boolean onMtrDex = false;
boolean oldonMtrDex = false;
boolean newKeyFlag = true;
// String who = "HC-05";
String received = "Received: ";
// ketay Bluetooth
KetaiBluetooth bt;
String info = "";
KetaiList klist;
PVector remoteMouse = new PVector();
ArrayList<String> devicesDiscovered = new ArrayList();
boolean isConfiguring = true;
String UIText;
String send;
// Coordinate area di scrittura
int ctrZoneX = 600;
int ctrZoneY = 150;
//Motore Destro
float valMDexOld = -1;//120
float valMDexMin = -255 ;
float valMDexMax = +255 ;
public float valMDex = 0 ; // Angolo del Servomotore 4
//Motore Sinistro
float valMSinOld = -1;
float valMSinMin = -255 ;
float valMSinMax = +255 ;
public float valMSin = 0 ; // Angolo del Servomotore 5
//Rotazione
float vRtzOld = 0;
float vRtzMin = -100 ;
float vRtzMax = +100 ;
public float vRtz = 0 ; // Angolo del Servomotore 6 - pRtze
//Rotazione
float vAvzOld = 0;
float vAvzMin = -100 ;
float vAvzMax = +100 ;
public float vAvz = 0 ; // Angolo del Servomotore 6 - pRtze
// Delay
float TimeDMin = 0 ;
float TimeDMax = 200 ;
public float TimeD = 10 ; // Rallentamento in millisecondi
float DlyMin = 1;
float DlyMax = 10;
// Incremento angolo
public float AngleInc = 3 ; // Rallentamento in millisecondi
String MotorDX, MotorSN;
Switch mRST = new Switch (ctrZoneX - 400, ctrZoneY + 000, 100, 100, mRSTLed, 200, 0, 0, 120 , 120, 120);
Switch mEQU = new Switch (ctrZoneX - 250, ctrZoneY + 000, 100, 100, mEQULed, 152, 228, 255, 120 , 120, 120);
Slider mDex = new Slider (ctrZoneX + 300, ctrZoneY + 150, -100, 500, valMDexMin, valMDexMax, valMDex, AngleInc, 0, 152, 0, 120 , 120, 120);
Slider mSin = new Slider (ctrZoneX - 400, ctrZoneY + 150, -100, 500, valMSinMin, valMSinMax, valMSin, AngleInc, 0, 152, 0, 120 , 120, 120);
Joy01 pAvz = new Joy01 (ctrZoneX - 250, ctrZoneY + 150, -500, 500, vAvzMin, vAvzMax, vRtzMin, vRtzMax,vAvz, AngleInc,vRtz, 2*AngleInc, 152, 228, 255, 120 , 120, 120);
//Joy01 S4 = new Joy01 ( 50, 50, -220, 300, -100, 100, 100, 100, 0, 2, 0, 3, 255, 0, 0, 120, 120, 120);
// // Joy01 ( x, y, a, b, minVX, maxVX, minVY, maxVY, VX, dVX, VY, dVY, cR, cG, cB, bR, bG, bB) {
/* Solo per Android inizio
//********************************************************************
// The following code is required to enable bluetooth at startup.
//********************************************************************
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bt = new KetaiBluetooth(this);
}
void onActivityResult(int requestCode, int resultCode, Intent data) {
bt.onActivityResult(requestCode, resultCode, data);
}
Solo per Android fine */
//********************************************************************
void setup()
{
//fullScreen();
//size(displayWidth, displayHeight);
//size(1820, 1024);
size(1200, 1024);
orientation(LANDSCAPE);
background(78, 93, 75);
stroke(255);
textSize(24);
Font1 = createFont("Comic Sans MS", 24);
// setta font per le scritte
textFont(Font1);
// /* Solo per Windows
//sceglie la porta di comunicazione
port = new Serial(this, "COM4", 9600);
port.bufferUntil('\n');
Android = false;
// Solo per Windows */
/* Solo per Android inizio
//start listening for BT connections
bt.start();
Android = true;
Solo per Android fine */
UIText = "d - discover devices\n" +
"b - make this device discoverable\n" +
"c - connect to device\n from discovered list.\n" +
"p - list paired devices\n" +
"i - Bluetooth info";
PitMotorReset ();
}
void draw()
{
if (isConfiguring)
{
ArrayList<String> names;
background(78, 93, 75);
// based on last key pressed lets display
// appropriately
if (key == 'i')
{
/* Solo per Android inizio
info = getBluetoothInformation();
println ("Info --> :" + info);
Solo per Android fine */
}
else
{
if (key == 'p')
{
/* Solo per Android inizio
info = "Paired Devices:\n";
names = bt.getPairedDeviceNames();
Solo per Android fine */
}
else
{
/* Solo per Android inizio
info = "Discovered Devices:\n";
names = bt.getDiscoveredDeviceNames();
Solo per Android fine */
}
/* Solo per Android inizio
for (int i=0; i < names.size(); i++)
{
info += "["+i+"] "+names.get(i).toString() + "\n";
}
Solo per Android fine */
}
/* Solo per Android inizio
text(UIText + "\n\n" + info, 5, 140);
Solo per Android fine */
// resetta il sistema e annulla le velocità
mRSTLed = mRST.flagOn;
if (mRSTLed != oldmRSTLed)
{
PitMotorReset ();
oldmRSTLed = mRSTLed;
//return;
}
onMtrSin = mRSTLed;
onMtrDex = mRSTLed;
mEQULed = mEQU.flagOn;
valMDex = mDex.Val;
valMSin = mSin.Val;
//vRtz = pRtz.Val;
//vAvz = pAvz.Val;
vRtz = pAvz.ValX;
vAvz = pAvz.ValY;
//String send;
/*
--------------------------------
Definizione comandi secondo protocollo PitProto
--------------------------------
*/
println ("DEX: ", valMDex, valMDexOld);
send = "ZVDX" + nf(int(valMDexOld+500), 4);
MotorDX = send;
if (valMDexOld != valMDex){
// /* Solo per Windows
port.write (send);
// /* // Solo per Windows */
/* Solo per Android inizio
byte [] data = send.getBytes();
bt.broadcast(data);
Solo per Android fine */
//println ("DEX: ", valMDex, valMSin, vRtz);
valMDexOld = valMDex;
}
send = "ZVSN" + nf(int(valMSinOld+500), 4);
MotorSN = send;
if (valMSinOld != valMSin){
// /* Solo per Windows
port.write (send);
// /* // Solo per Windows */
/* Solo per Android inizio
byte [] data = send.getBytes();
bt.broadcast(data);
Solo per Android fine */
//println ("SIN: ", valMDex, valMSin, vRtz);
valMSinOld = valMSin;
}
// accerazione / decelerazione
mEQULed = mEQU.flagOn;
if (mEQULed)
{
if (vAvzOld != vAvz)
{
if (vRtz >= 0)
{
//mDex.Val = (vRtzMax - vRtz) / (0 + vRtzMax) * mSin.Val;
mSin.Val = vAvz / vAvzMax * valMSinMax;
mDex.Val = (vRtzMax - vRtz) / (0 + vRtzMax) * mSin.Val;
}
else
{
// mSin.Val = (-vRtzMin + vRtz) / (0 - vRtzMin) * mDex.Val;
mDex.Val = vAvz / vAvzMax * valMSinMax;
mSin.Val = (-vRtzMin + vRtz) / (0 + vRtzMin) * mDex.Val;
}
valMDex = mDex.Val;
valMSin = mSin.Val;
//println ("AVZ: ", valMDex, valMSin, vRtz);
vAvzOld = vAvz;
}
if (vRtzOld != vRtz)
{
if (vRtz >= 0)
{
mDex.Val = (vRtzMax - vRtz) / (0 + vRtzMax) * mSin.Val;
valMDex = mDex.Val;
}
else
{
mSin.Val = (-vRtzMin + vRtz) / (0 - vRtzMin) * mDex.Val;
valMSin = mSin.Val;
}
vRtzOld = vRtz;
}
}
// Stato motore sinistro
if (onMtrSin != oldonMtrSin)
{
if (onMtrSin == true)
{
send = "ZSDX0001";
}
else
{
send = "ZSDX0000";
}
//println ("onMtrSin: ", onMtrSin, oldonMtrSin, " ", send);
// /* Solo per Windows
port.write (send);
// /* // Solo per Windows */
/* Solo per Android inizio
byte [] data = send.getBytes();
bt.broadcast(data);
Solo per Android fine */
oldonMtrSin = onMtrSin;
}
// Stato motore destro
if (onMtrDex != oldonMtrDex)
{
if (onMtrDex == true)
{
send = "ZSSN0001";
}
else
{
send = "ZSSN0000";
}
//println ("onMtrDex: ", onMtrDex, oldonMtrDex, " ", send);
// /* Solo per Windows
port.write (send);
// /* // Solo per Windows */
/* Solo per Android inizio
byte [] data = send.getBytes();
bt.broadcast(data);
Solo per Android fine */
oldonMtrDex = onMtrDex;
}
// ----------------------------
// Disegna lo stato dei motori
// ----------------------------
rectMode(CORNER);
fill(0 , 0, 0);
rect(ctrZoneX + 300, ctrZoneY + 700, 100, 100);
rect(ctrZoneX - 400, ctrZoneY + 700, 100, 100);
fill(255, 255, 0);
if (onMtrSin == true)
{
fill(0 , 152, 0);
}
else
{
fill(120 , 120, 120);
}
rect(ctrZoneX + 300 + 8, ctrZoneY + 700 + 8, 84, 84);
if (onMtrDex == true)
{
fill( 0, 152, 0);
}
else
{
fill(120 , 120, 120);
}
rect(ctrZoneX - 400 + 8, ctrZoneY + 700 + 8, 84, 84);
}
else
{
background(78, 93, 75);
pushStyle();
fill(255);
ellipse(mouseX, mouseY, 20, 20);
fill(0, 255, 0);
stroke(0, 255, 0);
ellipse(remoteMouse.x, remoteMouse.y, 20, 20);
popStyle();
}
/* Solo per Android inizio
//Solo Android
drawUI();
Solo per Android fine */
if (mousePressed == true)
{
mDex.mouseIn();
mSin.mouseIn();
//pRtz.mouseIn();
pAvz.mouseIn();
//mSOn.mouseIn();
//mDOn.mouseIn();
mRST.mouseIn();
mEQU.mouseIn();
}
//mSOn.update();
//mDOn.update();
mRST.update();
mEQU.update();
mDex.update();
mSin.update();
//pRtz.update();
pAvz.update();
fill(255);
//rotate (PI/2);
text("PitMotor V.2.10 - 02/2017" , 50, 50 + 850 * int(Android));
textSize(28);
text("www.zappoco.altervista.org" , 50, 50 + 30 + 850 * int(Android));
textSize(20);
if (flagDeb)
{
fill(mDex.colorR, mDex.colorG, mDex.colorB);
text("mDex: " + nfp(int(valMDexOld),3) + " " + MotorDX , ctrZoneX + 250 , ctrZoneY + 850);
fill(mSin.colorR, mSin.colorG, mSin.colorB);
text("mSin: " + nfp(int(valMSinOld),3) + " " + MotorSN , ctrZoneX -400 , ctrZoneY + 850);
fill(pAvz.colorR, pAvz.colorG, pAvz.colorB);
text("pAvz: " + nfp(int(vAvzOld),3), ctrZoneX - 50, ctrZoneY + 850);
//fill(pRtz.colorR, pRtz.colorG, pRtz.colorB);
text("pRtz: " + nfp(int(vRtzOld),3), ctrZoneX - 50, ctrZoneY + 820);
}
}
void PitMotorReset ()
{
mEQU.flagOn = true;
mDex.Val = 0;
mSin.Val = 0;
pAvz.ValX = 0;
pAvz.ValY = 0;
valMDexOld = mDex.Val;
valMSinOld = mSin.Val;
vRtzOld = pAvz.ValX;
vAvzOld = pAvz.ValY;
}
/* Solo per Android inizio
//Call back method to manage data received
void onBluetoothDataEvent(String who, byte[] data)
{
if (isConfiguring)
{
received += new String (data);
if (received.length() > 175)
received = ("Message to long!");
println (received);
return;
}
//KetaiOSCMessage is the same as OscMessage
// but allows construction by byte array
KetaiOSCMessage m = new KetaiOSCMessage(data);
if (m.isValid())
{
//println ( "m" + m);
if (m.checkAddrPattern("/remoteMouse/"))
{
if (m.checkTypetag("ii"))
{
remoteMouse.x = m.get(0).intValue();
remoteMouse.y = m.get(1).intValue();
}
}
}
}
String getBluetoothInformation()
{
String btInfo = "Server Running: ";
btInfo += bt.isStarted() + "\n";
btInfo += "Discovering: " + bt.isDiscovering() + "\n";
btInfo += "Device Discoverable: "+bt.isDiscoverable() + "\n";
btInfo += "\nConnected Devices: \n";
ArrayList<String> devices = bt.getConnectedDeviceNames();
for (String device: devices)
{
btInfo+= device+"\n";
}
return btInfo;
}
Solo per Android fine */
ZappocoS - febbraio, marzo 2017