Il video che vi vogliamo presentare in questo post riguarda un esempio di Automazione Industriale con Android. In particolare, vi faremo vedere un progetto che abbiamo realizzato in cui un touch HMI Android, Ltouch F, equipaggiato di un microprocessore Cortex A8 a 1Ghz controlla un’espansione RS485 analogica, nello specifico ho usato un modulo espansione bm6PTI.
Dall’interfaccia touch screen Android è possibile:
Acquisire distintamente 6 sonde di temperatura mod. PT100 classe B attraverso un’ espansione in RS485 utilizzando una comunicazione modbus ad una velocità di 19200 bps.
Volendo è possibile estendere l’applicazione aggiungendo altri moduli di espansione fino ad un totale di 250 bm6PTI con un’ acquisizione di 1500 sonde di temperatura.
- Eclipse IDE,
- Eclipse ADT plugin,
- Android SDK
Il progetto Android è formato dalla seguente struttura e file:
- la cartella /src, contiene l’Activity principale e la classe Java che definisce le firme delle funzioni della libreria modbus che verranno utilizzate nel progetto
- nella cartella libs/armeabi, si trova la libreria modbus
- la cartella res/layout, contiene il layout dell’Activity principale
- la cartella res/values, contiene il file string.xml
- nella cartella root, ci sarà il file AndroidManifest.xml che definisce il progetto Android
Nel blocco di codice che segue, vi presento il layout xml che è associato alla main activity.
Ho utilizzato un AbsoluteLayout, anche se altri layout più responsive potevano essere usati, in modo da riutilizzare l’applicazione in device con diverse risoluzioni. Ho volutamente scelto di non concentrarmi sui aspetti di design delle interfacce, ma bensì sugli aspetti più tecnici del progetto. Potreste essere voi, lettori, che attraverso la vostra fantasia create la miglior interfaccia che risponda alle vostre necessità.
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="match_parent" tools:context=".MainActivity" > <TextView android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_x="-346dp" android:layout_y="7dp" android:text="MAX" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="@color/red" /> <RelativeLayout android:id="@+id/relativeLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" > </RelativeLayout> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_x="37dp" android:layout_y="11dp" android:text="ANALOG 1" android:textAppearance="?android:attr/textAppearanceMedium" android:textSize="18dp" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_x="245dp" android:layout_y="11dp" android:text="ANALOG 2" android:textAppearance="?android:attr/textAppearanceMedium" android:textSize="18dp" /> <TextView android:id="@+id/textTemp2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_x="11dp" android:layout_y="23dp" android:text="0" android:textColor="@color/red" android:textSize="82dp" /> <TextView android:id="@+id/texTemp1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_x="229dp" android:layout_y="28dp" android:text="0" android:textColor="@color/red" android:textSize="82dp" /> <TextView android:id="@+id/TextTemp4" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_x="457dp" android:layout_y="28dp" android:text="0" android:textColor="@color/red" android:textSize="82dp" /> <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_x="479dp" android:layout_y="11dp" android:text="ANALOG 3" android:textAppearance="?android:attr/textAppearanceMedium" android:textSize="18dp" /> <TextView android:id="@+id/textTemp3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_x="12dp" android:layout_y="213dp" android:text="0" android:textColor="@color/red" android:textSize="82dp" /> <TextView android:id="@+id/TextView02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_x="246dp" android:layout_y="192dp" android:text="ANALOG 5" android:textAppearance="?android:attr/textAppearanceMedium" android:textSize="18dp" /> <TextView android:id="@+id/TextView03" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_x="50dp" android:layout_y="192dp" android:text="ANALOG 4" android:textAppearance="?android:attr/textAppearanceMedium" android:textSize="18dp" /> <TextView android:id="@+id/TextTemp6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_x="230dp" android:layout_y="213dp" android:text="0" android:textColor="@color/red" android:textSize="82dp" /> <TextView android:id="@+id/TextTemp5" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_x="452dp" android:layout_y="213dp" android:text="0" android:textColor="@color/red" android:textSize="82dp" /> <TextView android:id="@+id/TextView04" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_x="480dp" android:layout_y="192dp" android:text="ANALOG 6" android:textAppearance="?android:attr/textAppearanceMedium" android:textSize="18dp" />
La classe speciale ModbusLib contiene semplicemente la firma delle funzioni modbus che possono essere utilizzate nel progetto Android e che sono definite all’interno della libreria nativa.
package com.biemme.modbus; public class ModbusLib { public native static int openCom(int baudrate, long rtimeout, long wtimeout); public native static long ReadHoldingRegisters(int fd, int id, int address, int no_of_registers,int []holdingRegs); public native static int closeCom(int fd); static{ System.loadLibrary("com_biemme_modbus_ModbusLib"); } }
La classe che sarà eseguita all’avvio del progetto è MainActivity.java (specificato nel file AndroidManifest.xml).
Come si vede dalla firma, MainActivity estende la classe Activity per poter esser una finestra Android visualizzabile.
public class MainActivity extends Activity implements OnClickListener {
Secondo il lifecycle delle Activity in Android, il primo metodo che verrà eseguito in apertura della finestra è onAttach e successivamente OnCreate. All’interno di quest’ultimo blocco viene associato il content view (cioè il layout xml) e vengono memorizzati in attributi privati della classe i riferimenti agli widget grafici della finestra quali TextView, ImageView ecc…., in modo tale che le loro proprietà possano essere modificare in un secondo momento.
protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); temperature1= (TextView) findViewById(R.id.texTemp1); temperature2= (TextView) findViewById(R.id.textTemp2); temperature3= (TextView) findViewById(R.id.textTemp3); temperature4= (TextView) findViewById(R.id.TextTemp4); temperature5= (TextView) findViewById(R.id.TextTemp5); temperature6= (TextView) findViewById(R.id.TextTemp6); }
Il medoto onResume sarà eseguito non appena la finestra viene caricata, ma dopo onCreate oppure dopo che è stata messa in pausa. Contiene il codice che apre la porta seriale del touch screen Android e memorizza il riferimento all’id del file in una variable privata della classe. Inoltre, inizia il refresh dello status dei testi, mandando delle richieste modbus agli slave.
protected void onResume() { super.onResume(); if (fid == 0){ fid = ModbusLib.openCom(); Log.d("uart=",String.valueOf(fid)); } cancelReadThread(); workingthread=new ReadsWrites(); workingthread.start(); }
Nel prossimo post vi spiegheremo come, in una semplice riga di comando, si possono salvare le temperature in una sd così da realizzare un datalogger.