Raspberry PI 3 este cea mai populară placă de procesare IoT. Acest articol deschide seria de articole pe care vrem să o dedicăm domeniului IoT. Vom porni de la aplicațiile cele mai simple precum aprinderea unor leduri, controlul unei camere GoPro de la distanță, pentru ca în următoarele numere să prezentăm dezvoltarea unui sistem de check-in a persoanelor la un eveniment.
Vom folosi librăria Pi4J pentru a realiza comunicarea nativă cu Raspberry PI. Ceea ce ne interesează este controlul pinurilor GPIO de pe placă.
Primul exemplu practic pe care îl vom avea în acest articol este aprinderea a trei LED-uri conectate la placă. Numerotarea pinilor GPIO ai lui Raspberry PI 3 așa cum sunt folosiți de librăria PI4J îi puteți vedea în imaginea alăturată.
Fiecare LED are intrări de GND (ground) și IN care se va conecta la pinul care îi va controla. Pentru exemplul nostru, am ales pinul 4 și 11, iar pinul 14 pentru control (IN).
Codul este destul de simplu. Se definește un tabel cu pinii digitali ce vor fi folosiți:
private static Pin[] PINS={
RaspiPin.GPIO_11,
RaspiPin.GPIO_04,
RaspiPin.GPIO_21};
Inițializăm controllerul :
final GpioController gpio = GpioFactory.getInstance();
iar pentru fiecare pin folosit vom obține un obiect referință pentru control:
GpioPinDigitalOutput pinObj=
gpio.provisionDigitalOutputPin(
pin, pinName, PinState.LOW);
Așa cum se observă, se setează și starea inițială a acestuia: PinState.Low.
După inițializare, schimbarea tuturor LED-urilor se poate realiza ușor:
private static Pin[] PINS={
RaspiPin.GPIO_11,
RaspiPin.GPIO_04,
RaspiPin.GPIO_21};
Rulăm aplicația din linia de comandă:
sudo java -jar PITry-1.0-SNAPOT-jar-with -dependencies.jar org.tsm.iot.pi.MainController
Alternativ putem să folosim o consolă SSH / Putty pentru a rula aplicația. Transferul datelor se va realiza prin FTP. În acest mod vom putea folosi placa Raspberry PI remote. Pentru conectare vom folosi utilizatorul pi și parola raspberry.
În continuare, vom folosi un senzor shield pentru conectarea unui senzor de lumină, de temperatură și a unui buton la placa Raspberry PI. Fiecare senzor va avea trei intrări: ground, alimentare (5V sau 3.3V) și o intrare de pe senzor shield.
Este o interfață comună de transmitere a datelor între un microcontroller și diferite periferice, senzori, carduri. Folosește un canal de comunicare pentru ceas și una sau mai multe linii pentru transmiterea datelor. Reprezintă o soluție față de transmiterea datelor în mod asincron unde nu există o sincronizare între părți. De aici pot apărea probleme de transmitere a datelor, mai ales dacă emițătorul și receptorul rulează la viteze diferite. Soluția este de a folosi un ceas prin care se spune receptorului când să se citească date: low to high sau high to low.
Pentru citirea datelor de la client (slave) se va folosi o altă linie, MISO (Master - in, Slave Out) și de asemenea, o linie de selecție a clientului SS (Slave Select).
Pentru comunicarea cu shieldul SPI folosim pachetul com.pi4j.io.spi.
https://www.robofun.ro/raspberry-pi-si-componente/Kit-RASPBERRY-PI-B-pentru-incepatori
Pentru a putea folosi componenta, va trebui activat serviciul SPI pe Raspberry PI. După realizarea conexiunilor conform figurii de mai sus, putem să conectăm senzorii:
Canalul 0 - senzorul de temperatură Canalul 1 - senzorul de lumină Canalul 2 - butonul on/off
Vom folosi și o cameră video GoPro 3+ la care Raspberry Pi se va conecta wireless. Aplicația de mai jos va folosi un API nedocumentat de la GoPro pentru a realiza poze remote în momentul în care apăsăm butonul. Tot atunci vom aprinde și ledurile de la proiectul anterior.
O mare parte din codul de mai jos s-a folosit de exemplul librăriei Pi4J.
Inițializarea instanței SPI se realizează astfel:
// create SPI object instance for SPI
// for communication
spi = SpiFactory.getInstance(SpiChannel.CS0,
SpiDevice.DEFAULT_SPI_SPEED,
// default spi speed 1 MHz
SpiDevice.DEFAULT_SPI_MODE); // default spi mode 0
Întreg sistemul de monitorizare va fi realizat cu o buclă for
unde se citesc valorile fiecărui canal folosit:
// create SPI object instance for SPI
// for communication
spi = SpiFactory.getInstance(SpiChannel.CS0,
SpiDevice.DEFAULT_SPI_SPEED,
// default spi speed 1 MHz
SpiDevice.DEFAULT_SPI_MODE); // default spi mode 0
Vom folosi o clasă Console pentru afișarea datelor și posibilitatea de a ieși din bucla while
cu ajutorul CTRL-C
protected static final Console console = new Console();
console.title("<-- SPI Demo -->", "GoPro connection, temperature, light sensors and a launch button");
console.promptForExit();
Pentru fiecare din cele trei canale folosite vom avea un cod specific în metoda read(). Canalul 0 va afișa temperatura și se realizează o conversie în grade Celsius. Canalul 1 afișează intensitatea luminii. Atunci când este apăsat butonul, vom primi valoarea 1023, moment în care vom realiza o fotografie cu ajutorul camerei.
/**
* Read data via SPI bus from MCP3002 chip.
* @throws IOException
*/
private void read() throws IOException,
InterruptedException {
for(short channel = 0;
channel < ADC_CHANNEL_COUNT;
channel++){
int conversion_value = getConversionValue(channel);
switch (channel){
case 0:
double voltage = conversion_value * 3.3;
voltage /=1024.0;
double tempCelsius = (voltage-0.5)*100;
console.print(String.format(" | %06f",
(float)tempCelsius));
// print 4 digits with leading zeros
break;
case 1:
console.print(String.format(" | %04d | ",
conversion_value));
// print 4 digits with leading zeros
break;
case 2:
console.print(String.format(" | %04d | ",
conversion_value));
// print 4 digits with leading zeros
//button pressed
if (conversion_value>1000){
goProController.takePhoto();
piController.lightTime(1000l);
}
break;
default:
}
}
console.print(" |\r");
Thread.sleep(50);
}
Codul este destul de simplu. O evoluție ulterioară a acestuia va fi realizarea unei poze în momentul în care o persoană trece prin fața sa.
Așa cum menționam mai sus, vom folosi API-ul KonradIT. Vom folosi următoarele calluri:
http://10.5.5.9/camera/CM?t=&p=%01
http://10.5.5.9/camera/SH?t=&p=%01
Comenzile vor fi trimise folosind clasa standard URLConnection
:
private String
sendCommand(String urlStr) { URL url = null;
logger.info("opening url:" + urlStr);
InputStream in = null;
StringBuffer data = new StringBuffer();
logger.debug(urlStr);
try {
url = new URL(urlStr);
URLConnection urlConnection =
url.openConnection();
in = urlConnection.getInputStream();
char str;
logger.debug("available=" + in.available());
while ((str = (char) in.read()) != 0) {
logger.debug(str);
data.append(str);
}
}catch (IOException e){
logger.error(
"communication error:"+e.getMessage()); } finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
logger.error("unable to close the stream");
}
}
}
logger.debug(data.toString());
return data.toString();
}
}
Pentru realizarea unei fotografii folosim:
public void takePhoto() throws IOException { setConnectionPhoto();
sendCommand(TAKE_PHOTO);
}
Folosirea Java direct pe Raspberry PI este lipsită de limitări. S-au dus vremurile în care aveam Java Embedded. Puterea de procesare este suficient de mare astfel încât să lansăm chiar și un IntelliJ. Cel mai mare avantaj este de departe conexiunea cu senzorii și alte echipamente mobile, cum ar fi camera GoPro. Trecerea este foarte ușoară și necesită minime cunoștințe de Linux și de hardware.
În următoarele articole vom încerca să realizăm o soluție de monitorizare a participanților la un eveniment și de ce nu, chiar să le generăm badge-urile de acces.
de Ovidiu Mățan
de Bogdan Bucur
de Bogdan-Constantin Pîrvu , Constantin-Bălă Zamfirescu , Samuel Pușcașu , Vlad Ruxandu