Creazione programma lato Arduino
Benvenuti in questo nuovo tutorial, In questa nostra nuova puntata andremo a imparare come creare un collegamento tra il nostro smartphone (Android) e la nostra scheda Arduino. Non vi nascondo che alle prime volte che usavo questo codice spesso mi dava qualche problema, ma non spaventatevi, dopotutto questo codice una volta capito è molto semplice.
Inoltre ricordo che per funzionare tutto ciò necessitiamo di un modulo bluetooth come il modulo HC-05.
Visto che siamo in un tutorial di Arduino partiamo subito con il lato di codice che lo riguarda. Inanzitutto dobbiamo dichiarare la libreria Softwareserial,
#include <SoftwareSerial.h>
questa libreria ci permette di creare delle connessioni seriali su Pin digitali, inoltre ci permette di creare più connessioni con un baud di 115200.
Proseguiamo con andare a dichiarare la funzione costruttrice e come parametro gli passiamo 2 valori, che sono rispettivamente RX e il TX della nostra comunicazione.
SoftwareSerial mySerial(52,53);
Come precedentemente detto, possiamo usare anche dei Pin digitali come se fossero di comunicazione, purtroppo non tutti i Pin sono accettati. (Link per scoprire quali Pin sono accettati).
Tutto questo noi lo andremo a fare nella parte globale del nostro sketch, ma ora ci incentreremo nelle singole funzioni. Startiamo (Gergo personale sinonimo di partiamo) con la funzione setup.
void setup() { pinMode(key,OUTPUT);//key per il bluetooth serve per configuralo pinMode(btLed,OUTPUT);//notifica la ricezione di qualcosa digitalWrite(key,HIGH);//attiva key ma serve solo in fase iniziale
Nel setup andiamo semplicemente a dichiarare dei Pin per la key(o Wakeup) e il btLed. Il Pin key serve generalmente per entrare in AT mode (entrare in AT mode e i comandi) così da poter configurare il nostro modulo bluetooth. Invece il Pin assegnato alla variabile btLed è un Pin che verrà collegato a un led che si accenderà ogni qualvolta che la nostra scheda riceverà delle informazioni tramite bluetooth.
Inoltre creiamo una comunicazione seriale a un baud 38400 (ma la si può creare a differenti baud), sia per il monitor seriale che per la comunicazione bluetooth.
//inizializzazione porta seriale definendo il baud Serial.begin(38400); Serial.println("Type AT commands!"); // SoftwareSerial "com port" mySerial.begin(38400); }
Passando alla funzione loop la logica è molto semplice, viene fatto un controllo sulla variabile myserial ovvero sul bluetooth controllando se è disponibile.
Se il bluetooth risulta disponibile significa che sta ricevendo delle informazioni, di seguito Arduino accende il led sopra citato ed entra in un ciclo while per acquisire il valore ricevuto, questo succede perché il nostro bluetooth riceve byte per byte l’ informazione, di seguito ricostruisce il comando (o stringa) ricevuta facendo una somma di caratteri.
if (mySerial.available()) { digitalWrite(btLed,HIGH); while(mySerial.available()){ //leggo i valori ricevuti dal bluetooth command += (char)mySerial.read(); }
la seconda If presente nella nostra funzione serve per inviare dei comandi tramite la nostra scheda. questa if viene utilizzata principalmente per mandare comandi AT per configurare il modulo , ma può essere utiliazata anche per mandare dei parametri al nostro dispositivo.
// manda linput scritto dall' utente if (Serial.available()){ delay(10); // The DELAY! mySerial.write(Serial.read()); }
Questo codice è utilizzabile con bluetooth come HC-05, costruito per ricevere e inviare stringe, ma anche con moduli bluetooth come XS3868, costruito per l’invio e il controllo della musica.
Creazione programma lato Android
In questa seconda pagina andremo a a creare l’ applicazione Android per comunicare con la nostra scheda. Nello specifico vedremo come comunicare con il modulo bluetooth e quali modifiche andranno fatte nei vari file creati dal nostro IDE.
Per creare la nostra applicazione useremo, come ambiente di sviluppo, l’ IDE ufficiale di mamma google ovvero Android Studio (Download Android Studio).
Una piccola premessa non faró vedere come creare un nuovo progetto con questo IDE, visto che parto dal presupposto che le basi di questo software già le conosciate.
Inanzitutto creiamo un nuovo progetto in android studio e lo creiamo con la Blank Activity (con la schermata vuota).
una volta creato il progetto, andiamo nel file di configurazione chiamato AndroidManifest.xml e qui andremo aggiungere le seguenti righe all’interno del tag manifest.
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
Queste righe danno i permessi alla nostra applicazione per poter interagire con il modulo bluetooth che è presente sul nostro dispositivo.
Ora passiamo all’interfaccia e inseriamo un toggleButton all’interno della nostra app. questo button ci permetterà di connettere in nostro dispositivo con il modulo bluetooth collegato ad Arduino o a una scheda equivalente.
Una volta che abbiamo posizionato il toggleButton andiamo nel file MainActivity.java e dichiariamo le seguenti librerie
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import java.io.IOException; import java.io.OutputStream; import java.util.UUID;
di seguito dentro la classe andiamo a dichiarare le seguenti variabili
//per bluetooth public UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); BluetoothAdapter mBluetoothAdapter=null; BluetoothSocket mmSocket=null; BluetoothDevice mmDevice=null; OutputStream outStream;
Ora per connetterci al bluetooth creiamo un evento del toggle button dentro la funzione onCreate, l’evento in questione è il setOnClickListener.
//evento: tap sul togglebutton per la connessione del bluetooth tgb.setOnClickListener(new View.OnClickListener(){ public void onClick(View view){ if(tgb.isChecked())//controlla che sia attivo il toggle button{ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter == null)//controlla se il devices è supportato{ // IL BLUETOOTH NON E' SUPPORTATO Toast.makeText(MainActivity.this, "BlueTooth non supportato", Toast.LENGTH_LONG).show(); tgb.setChecked(false); } else{ if (!mBluetoothAdapter.isEnabled())//controlla che sia abilitato il devices { // NON E' ABILITATO IL BLUETOOTH Toast.makeText(MainActivity.this, "BlueTooth non abilitato", Toast.LENGTH_LONG).show(); tgb.setChecked(false); } else{ // IL BLUETOOTH E' ABILITATO mmDevice=mBluetoothAdapter.getRemoteDevice(<MAC>);//MAC address del bluetooth di arduino try{ mmSocket=mmDevice.createRfcommSocketToServiceRecord(uuid); } catch (IOException e){ tgb.setChecked(false); } try{ // CONNETTE IL DISPOSITIVO TRAMITE IL SOCKET mmSocket mmSocket.connect(); outStream = mmSocket.getOutputStream(); Toast.makeText(MainActivity.this, "ON", Toast.LENGTH_SHORT).show();//bluetooth è connesso } catch (IOException closeException){ tgb.setChecked(false); try{ //TENTA DI CHIUDERE IL SOCKET mmSocket.close(); } catch (IOException ceXC){ } Toast.makeText(MainActivity.this, "connessione non rieuscita", Toast.LENGTH_SHORT).show(); } } //CHIUDE l'else di isEnabled } //CHIUDE l'else di mBluetoothAdapter == null } // CHIUDE if (tgb.isChecked()) else{ try{ //TENTA DI CHIUDERE IL SOCKET outStream.close(); mmSocket.close(); } catch (IOException ceXC){} } } // CHIUDE public void OnClick(View view) });//chiude il tgb.listener
Tutte le spiegazioni di quello che fa questa funzione è scritto nei commenti tra il codice, ma ora vi faccio vedere come scrivere qualcosa nello stream di connessione tra i bluetooth. Tutto si basa su una funzione molto semplice, essa dovrà essere richiamata qual’ora, una volta connesso il bluetooth, si vogliano trasferire delle informazioni.
private void sendMessageBluetooth(String message) { if (outStream == null) { return; } byte[] msgBuffer = message.getBytes(); try { outStream.write(msgBuffer); } catch (IOException e) { Toast.makeText(MainActivity.this, "Messaggio non Inviato", Toast.LENGTH_SHORT).show(); } }
Buonasera, scusa l’ignoranza ma sono nuovo nel far comunicare arduino con app android!
Sto facendo la tesina per la maturità e mi servirebbe che l’app android avesse due pulsanti che comunichino due informazioni diverse (e dal lato android lo so fare) ma quello che invio poi in arduino non so come leggerlo.
Mi spiego meglio, la funzione che ha fatto lei legge, sì, ma non so come fare a capire cosa legge…. poichè se nel codice android invio “on” oppure semplicemente “o” , e nel codice dello sketch confronto che “command” == ‘o’ (per il secondo caso chiaramente) non va.
void loop() {
char command;
// put your main code here, to run repeatedly:
if (mySerial.available())
{
//digitalWrite(btLed,HIGH);
while(mySerial.available()){
//leggo i valori ricevuti dal bluetooth
command += (char)mySerial.read();
}
if(command == commandOn){
digitalWrite(btLed,HIGH);
}else if(command == commandOff){
digitalWrite(btLed,LOW);
}
….
}
Questa è una parte dello sketch dove commandOn = ‘o’; e commandOff=’f’;
In android invio ‘o’ se clicco su un pulsante e ‘f’ se ne clicco un altro.
Non riesco a capire come farlo funzionare, la ringrazio per la gentile attenzione e per il tempo che perderà, se ha voglia, di portarmi delle spiegazioni in merito alla faccenda.
In fede Andrea Mariotti.
Buonasera, scusa l’ignoranza ma sono nuovo nel far comunicare arduino con app android!
Sto facendo la tesina per la maturità e mi servirebbe che l’app android avesse due pulsanti che comunichino due informazioni diverse (e dal lato android lo so fare) ma quello che invio poi in arduino non so come leggerlo.
Mi spiego meglio, la funzione che ha fatto lei legge, sì, ma non so come fare a capire cosa legge…. poichè se nel codice android invio “on” oppure semplicemente “o” , e nel codice dello sketch confronto che “command” == ‘o’ (per il secondo caso chiaramente) non va.
void loop() {
char command;
// put your main code here, to run repeatedly:
if (mySerial.available())
{
//digitalWrite(btLed,HIGH);
while(mySerial.available()){
//leggo i valori ricevuti dal bluetooth
command += (char)mySerial.read();
}
if(command == commandOn){
digitalWrite(btLed,HIGH);
}else if(command == commandOff){
digitalWrite(btLed,LOW);
}
….
}
Questa è una parte dello sketch dove commandOn = ‘o’; e commandOff=’f’;
In android invio ‘o’ se clicco su un pulsante e ‘f’ se ne clicco un altro.
Non riesco a capire come farlo funzionare, la ringrazio per la gentile attenzione e per il tempo che perderà, se ha voglia, di portarmi delle spiegazioni in merito alla faccenda.
In fede Andrea Mariotti.
Salve Andrea, prima di tutto ti volevo far notare che se possiedi una variabile di tipo char (command nel tuo caso) non gli puoi assegnare un valore come “on”, in quanto il tipo di variabile char accetta solo UN carattere e non 2. Inoltre le chiedo se gentilmente mi può postare tutto il codice che usa e non solo una parte, perché una cosa che ho imparato nel corso di questi anni è che l’errore non sempre è dove sembra.
Come “allegato” al commento le metto il link di github dove ho postato tutto il mio codice che gira su Arduino (in quanto nell’articolo è solo una parte) se non lo ha già visto
https://github.com/SimOneGollo/motor/blob/master/motor.ino
Qualcuno potrebbe inviarmi il progetto in android studio per l’ app a
stefano.mancon@gmail.com
grazie.
Qualcuno potrebbe inviarmi il progetto in android studio per l’ app a
stefano.mancon@gmail.com
grazie.
buonasera, mi sto documentando sul come gestire queste funzionalità con arduino e volevo sapere se il modulo bluetooth può comunicare solo variabili di tipo char oppure può inviare anche variabili numeriche di tipo float, e se si devo includere librerie particolari o fare delle grosse modifiche al programma?
Salve lenny, io ho usato il char perché mi risultava più semplice da gestire, visto che la funzione write della classe OutputStream accetta solo variabili di tipo byte(in questo caso un vettore) e int (in questo ultimo caso, per quanto ho letto nella documentazione, invia solo i otto bit meno significativi della variabile).
Non so se sia in grado di gestire numeri di tipo float ma potresti usare la funzione writeFloat della classe DataOutputStream ma attento che prima di inviare il dato lo converte in intero e poi lo invia, e invia prima i bit più significativi e poi con le giuste conversioni da parte di arduino lo ri converti in float
Per maggiori informazioni della libreria DataOutputStream: https://developer.android.com/reference/java/io/DataOutputStream.html
buonasera, mi sto documentando sul come gestire queste funzionalità con arduino e volevo sapere se il modulo bluetooth può comunicare solo variabili di tipo char oppure può inviare anche variabili numeriche di tipo float, e se si devo includere librerie particolari o fare delle grosse modifiche al programma?
Salve lenny, io ho usato il char perché mi risultava più semplice da gestire, visto che la funzione write della classe OutputStream accetta solo variabili di tipo byte(in questo caso un vettore) e int (in questo ultimo caso, per quanto ho letto nella documentazione, invia solo i otto bit meno significativi della variabile).
Non so se sia in grado di gestire numeri di tipo float ma potresti usare la funzione writeFloat della classe DataOutputStream ma attento che prima di inviare il dato lo converte in intero e poi lo invia, e invia prima i bit più significativi e poi con le giuste conversioni da parte di arduino lo ri converti in float
Per maggiori informazioni della libreria DataOutputStream: https://developer.android.com/reference/java/io/DataOutputStream.html
Salve volevo farti una domanda, ho fatto un app per android che si interfaccia via Bluetooth con arduino.
il sottoprogramma di invio è praticamente come il tuo, tranne che dopo aver chiamato OutputStream.write(message); ho anche aggiunto OutputStream.flush(); per evitari che si impalli dopo che invio molta roba. risultato, si impalla lo stesso. Ti è già successo una cosa del genere? sapresti come risolverla?
Salve Federico, a me non è mai successo. A volte mi capita che il bluetooth non si connetta propriamente nei migliori dei modi (e di conseguenza mandando in crash la applicazione). L’ unico problema che io ho riscontrato nel mandare il messaggio e che se Arduino non è ben sincronizzato con Android, potrebbe leggere lo stesso messaggio 2 volte. Ad esempio io inviavo la lettera A e Arduino leggeva AA. Questa cosa lo potuta risolvere mettendo un delay.
Ma ti si impalla anche inviando piccole quantità di dati (singoli byte) ??
Salve volevo farti una domanda, ho fatto un app per android che si interfaccia via Bluetooth con arduino.
il sottoprogramma di invio è praticamente come il tuo, tranne che dopo aver chiamato OutputStream.write(message); ho anche aggiunto OutputStream.flush(); per evitari che si impalli dopo che invio molta roba. risultato, si impalla lo stesso. Ti è già successo una cosa del genere? sapresti come risolverla?
Salve Federico, a me non è mai successo. A volte mi capita che il bluetooth non si connetta propriamente nei migliori dei modi (e di conseguenza mandando in crash la applicazione). L’ unico problema che io ho riscontrato nel mandare il messaggio e che se Arduino non è ben sincronizzato con Android, potrebbe leggere lo stesso messaggio 2 volte. Ad esempio io inviavo la lettera A e Arduino leggeva AA. Questa cosa lo potuta risolvere mettendo un delay.
Ma ti si impalla anche inviando piccole quantità di dati (singoli byte) ??
Buonasera Simone, potresti condividere lo script di Android Studio ? Sono inesperto nell’utilizzare Android Studio e per la maturità dovrei portare per un app che manda caratteri chat ad Arduino ( realizzo una casa domotica). Grazie in anticipo
Salve Christian, il programma completo lo puoi trovare su github passando per il seguente link -> https://github.com/SimOneGollo/MCAC.git
Buonasera Simone, potresti condividere lo script di Android Studio ? Sono inesperto nell’utilizzare Android Studio e per la maturità dovrei portare per un app che manda caratteri chat ad Arduino ( realizzo una casa domotica). Grazie in anticipo
Salve Christian, il programma completo lo puoi trovare su github passando per il seguente link -> https://github.com/SimOneGollo/MCAC.git
Salve. Come posso fare nel momento in cui voglio mettere dei pulsanti al posto del joystick?
Semplicemente crei dei pulsanti, e nella funzione che andrai a fare per gestire l’evento del tap sul pulsante, richiami la funzione “sendMessageBluetooth(String message)” con un parametro che vuoi spedire (Dovrà essere un valore che decidi tu e che sai che quel valore indica quello specifico pulsante)
salve ragazzi,
ho creato una app (con app inventor2) che mi legge una variabile tramite bluetooth. La stessa variabile la visualizzo su un display lcd collegato direttamente ad arduino. Quello che noto è un ritardo nella visualizzazione del dato sulla app (circa un secondo), rispetto al display.
C’è un modo per “sincronizzare” le due visualizzazioni? oppure questo ritardo è fisiologico e non si può fare nulla?
grazie per una risposta
Salve Domenico,
darti una risposta certa faccio fatica perché appinvetor2 lo conosco per sentito dire ma non l’ho mai usato. Sinceramente penso sia un problema fisiologico in quanto effettivamente non sappiamo come vengono tradotti i blocchi in codice, anche se di solito questi applicativi del MIT dovrebbero avere codice sorgente aperto. Facendo l’app con AndroidStudio, il delay tra l’input e il cambio di stato effettivo del mio Arduino passava molto meno di un secondo (parliamo dell’ordine di un centinaio di millisecondi).
Vorrei inoltre ricordare che Arduino fa girare un singolo processo e che quindi se scrivi su lcd non stai inviando byte sulla seriale per il bluetooth quindi (a meno che ti non l’abbia già fatto) ti consiglio di mandare prima il messaggio con il bluetooth e poi stampare quel messaggio sul lcd di Arduino.
Comunque sia è hai riscontrato un problema interessante, se riesci a trovare una risposta esatta a cosa possa essere facci sapere.
salve ragazzi,
ho creato una app (con app inventor2) che mi legge una variabile tramite bluetooth. La stessa variabile la visualizzo su un display lcd collegato direttamente ad arduino. Quello che noto è un ritardo nella visualizzazione del dato sulla app (circa un secondo), rispetto al display.
C’è un modo per “sincronizzare” le due visualizzazioni? oppure questo ritardo è fisiologico e non si può fare nulla?
grazie per una risposta
Salve Domenico,
darti una risposta certa faccio fatica perché appinvetor2 lo conosco per sentito dire ma non l’ho mai usato. Sinceramente penso sia un problema fisiologico in quanto effettivamente non sappiamo come vengono tradotti i blocchi in codice, anche se di solito questi applicativi del MIT dovrebbero avere codice sorgente aperto. Facendo l’app con AndroidStudio, il delay tra l’input e il cambio di stato effettivo del mio Arduino passava molto meno di un secondo (parliamo dell’ordine di un centinaio di millisecondi).
Vorrei inoltre ricordare che Arduino fa girare un singolo processo e che quindi se scrivi su lcd non stai inviando byte sulla seriale per il bluetooth quindi (a meno che ti non l’abbia già fatto) ti consiglio di mandare prima il messaggio con il bluetooth e poi stampare quel messaggio sul lcd di Arduino.
Comunque sia è hai riscontrato un problema interessante, se riesci a trovare una risposta esatta a cosa possa essere facci sapere.
Salve, una domanda io ho gia un applicazione sul telefono per farla comunicare basta che compro solo questo tipo di bluetooth?
Grazie
Il codice originario era pensato per il modulo bluetooth HC-05. Nonostante ciò dovrebbe funzionare con tutti quei moduli bluetooth che fanno uso della interfaccia seriale UART (i famosi pin RX, TX).