Proiect Cloud’s Lights

Controlul iluminatului dintr-o locuință sau chiar dintr-o incintă mai mare prin intermediul serviciilor de cloud a devenit o soluție întâlnită din ce în ce mai des în aplicațiile de tip Home Automation sau Building Automation. Problema majoră a dispozitivelor ce permit acest tip de control este prețul foarte mare. Fie că alegem dispozitive conectate direct la Internet (becuri WiFi) fie că alegem soluții bazate pe controlere specializate de tip routere IoT, costul dispozitivelor necesare face ca aceste soluții să nu fie larg accesibile. În cadrul proiectului de față vom încerca să oferim o soluție fiabilă și accesibilă la problema controlului iluminatului într-o locuință prin intermediul rețelei Internet utilizând un serviciu de cloud.

Pentru controlul elementelor de iluminare vom utiliza dispozitive comutator pentru becuri din seria Conrad RSL comercializate în România de German Electronics SRL:

 

2

 

Avantajul acestor dispozitive este faptul că elementul de iluminare este separat, pot fi folosite cu orice tip de bec cu soclu E27 (max. 100W) și în momentul în care becul se arde nu trebuie să schimbăm și elementul de comandă (situație des întâlnită la becurile WiFi). Aceste dispozitive permit comanda radio de la distanță în bandă ISM de 433MHz – distanță de comandă de până la 25m (suficientă pentru majoritatea apartamentelor). Comanda se poate efectua cu orice telecomandă din seria Conrad RSL dar pe lângă telecomandă se pot folosi și comutatoare de perete din seria Conrad RSL:

3

Comutatoarele de perete funcționează pe baza unei baterii de 12V (tip 27A) făcându-le absolut independente de poziționarea rețelei de alimentare cu energie electrică – se pot aplica pe perete oriunde fără a avea nevoie de doză de conectare. Comutatoarele suplinesc telecomenzile permițând comanda a unui sau a două comutatoare de becuri (poziție închis/deschis).

Comutatorul de alimentare a becurilor necesită înregistrarea elementelor de comandă radio (telecomandă, comutator de perete). Butonul prezent la baza soclului poate fi utilizat pentru comanda manuală a becului dar și pentru înregistrarea codurilor de comandă (apăsare prelungă). Pentru operarea corectă a comutatorului este necesară citirea cu atenție a manualului furnizat de producător. Chiar dacă instalarea comutatorului de becuri este asemănătoare cu schimbul unui bec trebuie ca instalarea să se facă cu maximă grijă deoarece există pericol de electrocutare (opriți alimentarea cu energie electrică înainte de instalare!!!).

Pentru a putea reproduce comanda radio a unui astfel de comutator este necesară realizarea unui montaj simplu bazat pe o placă de dezvoltare Arduino Uno sau echivalentă și un receptor radio 433MHz.

 

4

 

Rulând exemplul ReceiveDemo_Simple al bibliotecii software rc-switch vom putea vizualiza tipul de cod și codul emis la fiecare apăsare de buton al comutatorului (sau telecomenzii):

5

https://github.com/sui77/rc-switch/

 

Codurile obținute (emise de comutator) se vor copia pentru a fi utilizate în program. Sistemul de comandă va fi format dintr-o placă de dezvoltare Adafruit Feather HUZZAH și un emițător radio 433MHz:

6

 

Emițătorul radio funcționează la o tensiune de 5V și din acest motiv este alimentat de la pinul USB (tensiunea furnizată de conexiunea USB a plăcii) – sistemul nu va funcționa corect dacă placa de dezvoltare este alimentată de la un acumulator. Pinul de date al emițătorului se va conecta la pinul 0 al plăcii de dezvoltare. Pentru mai multe informații despre instalarea și utilizarea plăcii Adafruit Feather HUZZAH puteți consulta:

Overview | Adafruit Feather HUZZAH ESP8266 | Adafruit Learning System

https://learn.adafruit.com/adafruit-feather-huzzah-esp8266/

Programul sistemului va utiliza mediul de dezvoltare Arduino IDE 1.8.1 și bibliotecile software: rc-switch 2.6.2, PubSubClient 2.6.0 (pentru comunicația MQTT cu serviciul de cloud), ArduinJson 5.8.3 (pentru interpretarea mesajelor provenite de la serviciul de cloud) și ESP8266WiFi 1.0.0.

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

#include <ESP8266WiFi.h>

#include <PubSubClient.h>

#include <ArduinoJson.h>

Atenție!!! În cadrul bibliotecii PubSubClient este necesară modificarea fișierului PubSubClient.h: constanta MQTT_MAX_PACKET_SIZE trebuie schimbată din 128 în 256.

Pentru a permite conectarea la Internet este necesară personalizarea datelor de conectare la rețeaua WiFi locală (care să permită accesul la Internet):

const char* ssid     = “…”;

const char* password = “…”;

Constantele API_KEY, PROJECT_ID și DEVICE_UUID vor fi modificate conform proiectului înregistrat în serviciul de cloud (etapă explicată în secțiunea următoare).

#define API_KEY         “…”

#define PROJECT_ID      “…”

#define ACTUATOR_NAME1   “LightSocket1”

#define ACTUATOR_NAME2   “LightSocket2”

#define ACTUATOR_NAME3   “LightSocket3”

#define ACTUATOR_NAME4   “AllLightSockets”

#define DEVICE_UUID     “…”

#define sec 1000

char clientId[]          = “Feather_HUZZAH”;

char actuatorTopic1[]     = “/a/”API_KEY”/p/”PROJECT_ID”/d/”DEVICE_UUID”/actuator/”ACTUATOR_NAME1″/state”;

char actuatorTopic2[]     = “/a/”API_KEY”/p/”PROJECT_ID”/d/”DEVICE_UUID”/actuator/”ACTUATOR_NAME2″/state”;

char actuatorTopic3[]     = “/a/”API_KEY”/p/”PROJECT_ID”/d/”DEVICE_UUID”/actuator

/”ACTUATOR_NAME3″/state”;

char actuatorTopic4[]     = “/a/”API_KEY”/p/”PROJECT_ID”/d/”DEVICE_UUID”/actuator

/”ACTUATOR_NAME4″/state”;

char server[]            = “mqtt.devicehub.net”;

char message_buffer[150];

WiFiClient apiClient;

 

Procedura callback este necesară în cadrul comunicației MQTT – ea preia mesajele venite de la serviciul de cloud și le transpune în comenzi radio destinate comutatoarelor de becuri.

 

void callback(char* topic, byte* payload,

unsigned int length)

{

  StaticJsonBuffer<200> jsonBuffer;

  for(int i=0; i<length; i++)

  { message_buffer[i] = payload[i]; }

  JsonObject& root =

                 jsonBuffer.parseObject(message_buffer);

  if (!root.success()) {

    Serial.println(“parseObject() failed”);

    return;

  }

  boolean onoff = root[“state”];

  if(String(topic) == String(actuatorTopic1)){

      Serial.println(“message arrived: ” + String(onoff) + ” from Light Switch 1″);

      if (onoff) mySwitch.send(2189781504,32);

      else if (!onoff) mySwitch.send(2323999232,32);

  }else if ((String(topic) == String(actuatorTopic2))){

      Serial.println(“message arrived: ” + String(onoff) + ” from Light Switch 2″);

      if (onoff) mySwitch.send(2424662528,32);

      else if (!onoff) mySwitch.send(2558880256,32);

  }else if ((String(topic) == String(actuatorTopic3))){

      Serial.println(“message arrived: ” + String(onoff) + ” from Light Switch 3″);

      if (onoff) mySwitch.send(2625989120,32);

      else if (!onoff) mySwitch.send(2458216960,32);

  }else if ((String(topic) == String(actuatorTopic4))){

      Serial.println(“message arrived: ” + String(onoff) + ” from All Light Switch”);

      if (onoff) mySwitch.send(2474994176,32);

      else if (!onoff) mySwitch.send(2743429632,32);

  }

}

PubSubClient client(server, 1883, callback, apiClient);

 

În cadrul secțiunii setup() se va inițializa conexiunea WiFi și conexiunea MQTT cu serverul de cloud.

 

void setup() {

  Serial.begin(9600);

  delay(10);

  Serial.println();

  Serial.println();

  Serial.print(“Connecting to “);

  Serial.println(ssid);

  WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {

    delay(500);

    Serial.print(“.”);

  }

  Serial.println(“”);

  Serial.println(“WiFi connected”); 

  Serial.println(“IP address: “);

  Serial.println(WiFi.localIP());

  Serial.println(“\nStarting connection to server…”);

  if(client.connect(clientId)) 

  {

    client.subscribe(actuatorTopic1);

    client.subscribe(actuatorTopic2);

    client.subscribe(actuatorTopic3);

    client.subscribe(actuatorTopic4);

    Serial.println(“Successfuly connected and running!”);

  }

  else 

  {

    Serial.println(“Connection problem”);

  }

  mySwitch.enableTransmit(0);

  mySwitch.setProtocol(2);

  mySwitch.setRepeatTransmit(3);

  delay(500);

}

 

Secțiunea loop() are sarcina de a supraveghea conexiunea MQTT și de a o reface în cazul unei deconectări – prelucrarea mesajelor de comandă se face în procedura callback.

 

void loop() {

  if (!client.connected())

  { Serial.println(“reconnecting …”);

    client.connect(clientId);

    delay(3*sec);

    client.subscribe(actuatorTopic1);

    client.subscribe(actuatorTopic2);

    client.subscribe(actuatorTopic3);

    client.subscribe(actuatorTopic4);

  }

    client.loop();

}

Ca și serviciu de comandă cloud vom utiliza Devicehub.net – un serviciu de cloud specializat IoT care permite înregistrare gratuită a unui cont de dezvoltator (cont cu facilități suficiente pentru proiectul de față: 100 de dispozitive IoT, 100 de senzori . elemente de acționare, 10 mesaje/secundă, 30 milioane de mesaje/lună).

7

 

După înregistrarea contului se va genera un nou proiect denumit CloudLights (numele se poate modifica). În cadrul acestui proiect se vor adăuga 4 elemente de acționare digitale (Actuator / Digital) pe care le vom numi: LightSocket1, LightSocket2, LightSocket3, AllLightSockets (modificarea acestor denumiri necesită modificarea valorii constantelor ACTUATOR_NAME din program).  Acum se pot personaliza datele de conectare din program preluând cele necesare din secțiunea Development Information.

8

La execuție programul va avea următoarea raportare pe portul serial (fiecare comandă de închidere / deschidere se va materializa într-un mesaj provenit de la serverul de cloud):

9

La fiecare nouă conectare serviciul de cloud va realiza o inițializare cu starea memorată a comenzilor dar, având în vedere caracterul unidirecțional al comunicației radio, starea comenzilor din serviciul cloud nu oferă certitudinea unei anumite stări pentru comutatoare (starea acestora poate să fie modificată manual sau cu ajutorul unei telecomenzi).

Având în vedere diversitatea de dispozitive telecomandate din familia Conrad RSL aplicația de comandă se poate extinde incluzând și alte dispozitive: prize telecomandate, întrerupătoarea de perete sau comutatoare încastrabile:

10

Comutatoarele încastrabile pot fi instalate în doze de derivație și pot servi pentru a controla alimentarea cu energie a unor secțiuni din rețeaua electrică (o anexă din gospodărie de exemplu) dar instalarea lor necesită pregătire de specialitate – nu efectuați modificări ale instalației electrice singuri, apelați la un electrician!!!

 

În cazul în care doriți să dezvoltați sistemul propus puteți parcurge și următoarele proiecte asemănătoare:

 

ESP8266 Remote Controlled Sockets

http://randomnerdtutorials.com/esp8266-remote-controlled-sockets/

 

Switch a cheep 433Mhz RC-Socket  by an Adfafruit HUZZAH ESP8266 WebServer

http://fritzing.org/projects/esp8266-433mhz-rc-socket-switch

 

Using an ESP8266 to Control Mains Sockets Using 433mhz Transmitter and Receiver

http://www.instructables.com/id/Using-an-ESP8266-to-Control-Mains-Sockets-Using-43

Proiect Local Area Power Plugs

Controlul centralizat al alimentării cu energie electrică a consumatorilor este o problemă în permanentă căutare de noi soluții și de noi modalități de implementare a acestora. Chiar dacă vorbim de consumatori casnici – aplicații de automatizare a locuinței – și chiar dacă există soluții deja cunoscute de implementare a controlului centralizat la acest nivel, considerăm subiectul de interes suficient de mare încât să propunem o soluție nouă elegantă și extraordinar de simplu de implementat. Bazându-ne pe elemente de alimentare comandante în bandă ISM de 433MHz și pe o placă de dezvoltare Arduino Leonardo ETH vom dezvolta o aplicație de comandă centralizată de comandă prin intermediul rețelei locale.

Având în vedere faptul că, construirea de la zero a unui element de comandă de putere (220V) este riscantă (prezintă risc de electrocutare și de incendiu) materialul vine cu propunerea de utilizare a unor elemente prefabricate / comercializate ca dispozitive de sine stătătoare, și anume prizele intermediare telecomandate Conrad RSL comercializate la noi în țară de German Electronics SRL:

1

Aceste prize sunt controlate prin intermediul unei telecomenzi radio (bandă 433MHz) de la o distanță de maxim 30m (suficient pentru un apartament obișnuit). În cadrul sistemului nostru vom înlocui telecomanda furnizată de producător cu un sistem de rețea bazat pe placa Arduino Leonardo ETH (telecomanda va putea fi folosită în paralel cu sistemul de comandă propus). Pentru a putea implementa sistemul de comandă este necesară observarea codurilor emise de telecomanda oferită de producător, acest lucru se poate face cu ajutorul unui sistem simplu compus dintr-o placă Arduino Uno (sau orice versiune de placă Arduino compatibilă) și un receptor radio 433MHz:

2

Rulând exemplul ReceiveDemo_Simple al bibliotecii software rc-switch vom putea vizualiza tipul de cod și codul emis la fiecare apăsare de buton al telecomenzii:

3

Se observă că seria Conrad RSL folosește un cod de comandă pe 32 de biți. Din cei 32 de biți trimiși la fiecare apăsare de buton: primii doi biți sunt întotdeauna 10 (secvență de sincronizare), următorii 6 codează canalul (I-IV), numărul butonului (1-4) și comanda (On, Off, All-On, All-Off) iar ultimii 24 reprezintă un identificator unic al telecomenzii – cu alte cuvinte la apăsarea diverselor butoane ale aceleiași telecomandă vor varia doar șase biți (ce notați cu roșu) – 64 de combinații posibile.

10 00 00 10 100001010110101000000000

Pentru mai multe informații legate de protocolul folosit de dispozitivele Conrad RSL puteți consulta și discuția de la adresa:

Conrad RSL Switch

https://forum.pilight.org/Thread-Fully-Supported-Conrad-RSL-Switch?page=7

Spre deosebire de alte prize telecomandate în bandă ISM, prizele Conrad RSL permit învățarea codurilor emise de telecomandă în mod dinamic. Butonul roșu de pe priză folosește la deschiderea / închiderea manuală a prizei dar, prin apăsare prelungă, și la învățarea unui nou cod de comandă. Fiecare priză poate memora până la 8 coduri de comandă diferite. Priza memorează și în lipsa alimentării cu energie (deconectată) codurile învățate și starea (dacă este deconectată în starea deschis la reconectare va avea starea deschis). În plus fiecare priză integrează protecție la supra-sarcină. La prima punere în funcțiune este necesară citirea cu atenție a documentației pusă la dispoziție de producător pentru înțelegerea exactă a modului de operare.

Comparativ, cu privire la protocolul radio de comunicație, se poate parcurge următorul material pentru a înțelege diferențele față de alte protocoale specifice unor produse similare:

Intertechno Code Berechnung

https://wiki.fhem.de/wiki/Intertechno_Code_Berechnung

După determinarea codurilor emise de telecomandă se poate trece la contruirea sistemului de comandă. Acesta se bazează pe o placă Arduino Leonardo ETH și o telecomandă radio 433MHz Arduino. Opțional, pentru a putea supraveghera sistemul, se poate adăuga un ecran LCD 20×4 I2C. Schema de interconectare este următoarea:

4

Ambele componente ale sistemului se alimentează la 5V. Emițătorul radio se va conecta la pinul digital 10 al plăcii de dezvoltare iar ecranul LCD (modulul I2C) va utiliza magistrala I2C a plăcii de dezvoltare (pinii 2 și 3).

Programul sistemului va utiliza bibiliotecile software rc-switch, LiquidTWI și Ethernet2 (biblioteca necesară noului chip Wiznet 5500 cu care este echipată placa Arduino Leonardo ETH):

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

#include <Wire.h>

#include <LiquidTWI.h>

LiquidTWI lcd(0);

#include <SPI.h>

#include <Ethernet2.h>

EthernetServer server(80);

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

String HTTP_req;

boolean plug1_status = 0;

boolean plug2_status = 0;

boolean plug3_status = 0;

În cadrul secțiunii setup() vom inițializa componentele de lucru cu ecranul LCD, cu emițătorul radio și cu controlerul ethernet (sistemul va funcționa într-o rețea locală bazată pe configurare dinamică – DHCP):

void setup() {

  mySwitch.enableTransmit(10);

  mySwitch.setProtocol(2);

  mySwitch.setRepeatTransmit(3);

  lcd.begin(20, 4);

  lcd.clear();

  lcd.setCursor(0,0);

  if (Ethernet.begin(mac) == 0) { lcd.print(F(“Failed

DHCP”)); while(1); }

  else

    { server.begin();

      lcd.print(“SrvIP: “);

      lcd.print(Ethernet.localIP());

    }

  delay(5000); }

Secțiunea loop() implementează interfața web de comandă (captură de ecran) și se va ocupa cu trimiterea comenzilor radio provenite de la utilizator pe această cale:

5

void loop() {

  EthernetClient client = server.available();

  if (client) {

    boolean currentLineIsBlank = true;

    while (client.connected()) {

      if (client.available()) {

        char c = client.read();

        HTTP_req += c;

        if (c == ‘\n’ && currentLineIsBlank) {

          client.println(F(“HTTP/1.1 200 OK”));

          client.println(F(“Content-Type: text/html”));

          client.println(F(“Connection: close”));

          client.println();

          client.println(F(“<!DOCTYPE HTML>”));

          client.println(F(“<html>”));

          client.println(F(“<head>”));

          client.println(F(“<title>Local Area PowerPlugs</title>”));

          client.println(F(“</head>”));

          client.println(F(“<body>”));

          client.println(F(“<h1>Local Area Power Plugs</h1>”));

          client.println(F(“<p>Click to switch plugs on and off.</p>”));

          client.println(F(“Power Plug 1: “));

          client.println(F(“<button

onclick=””window.location.href=’/?plug1on'””>Turn On Plug1</button>”));

          client.println(F(“<button onclick=””window.location.href=’/?plug1off'””>Turn Off Plug1</button><br>”));

          client.println(F(“Power Plug 2: “));

          client.println(F(“<button

             onclick=””window.location.href=’/?plug2on'””>Turn On Plug2</button>”));

          client.println(F(“<button onclick=””window.location.href=’/?plug2off'””>Turn Off Plug2</button><br>”));

          client.println(F(“Power Plug 3: “));

          client.println(F(“<button onclick=””window.location.href=’/?plug3on'””>Turn On Plug3</button>”));

client.println(F(“<button onclick=””window.location.href=’/?plug3off'””>Turn Off Plug3</button><br><br>”));

          client.println(F(“<b>All Power Plugs: </b>”));

          client.println(F(“<button

onclick=””window.location.href=’/?plugson'””>Turn On All Plugs</button>”));

          client.println(F(“<button onclick=””window.location.href=’/?plugsoff'””>Turn Off All Plugs</button><br>”));

          client.println(F(“</body>”));

          client.println(F(“</html>”));

          break;

        }

        if (c == ‘\n’) {

          currentLineIsBlank = true;

        }

        else if (c != ‘\r’) {

          currentLineIsBlank = false;

        }

      }

      }

    delay(1);

    client.stop();

    if (HTTP_req.indexOf(“?plug1on”) >0){

      mySwitch.send(2189781504,32);

      lcd.setCursor(0,1);

      lcd.print(“Plug1 On “);

    }

    else if (HTTP_req.indexOf(“?plug1off”) >0) {

      mySwitch.send(2323999232,32);

      lcd.setCursor(0,1);

      lcd.print(“Plug1 Off”);

    }

    else if (HTTP_req.indexOf(“?plug2on”) >0) {

      mySwitch.send(2424662528,32);

      lcd.setCursor(0,2);

      lcd.print(“Plug2 On “);

    }

    else if (HTTP_req.indexOf(“?plug2off”) >0) {

      mySwitch.send(2558880256,32); 

      lcd.setCursor(0,2);

      lcd.print(“Plug2 Off”);

    }

    else if (HTTP_req.indexOf(“?plug3on”) >0) {

       mySwitch.send(2625989120,32);

       lcd.setCursor(0,3);

       lcd.print(“Plug3 On “);

    }

    else if (HTTP_req.indexOf(“?plug3off”) >0) {

      mySwitch.send(2458216960,32);  

      lcd.setCursor(0,3);

      lcd.print(“Plug3 Off”);

    }

    else if (HTTP_req.indexOf(“?plugson”) >0) {

      mySwitch.send(2474994176,32);

      lcd.setCursor(0,1);

      lcd.print(“Plug1 On “);

      lcd.setCursor(0,2);

      lcd.print(“Plug2 On “);

      lcd.setCursor(0,3);

      lcd.print(“Plug3 On “);

    }

    else if (HTTP_req.indexOf(“?plugsoff”) >0) {

      mySwitch.send(2743429632,32);

      lcd.setCursor(0,1);

      lcd.print(“Plug1 Off”);

      lcd.setCursor(0,2);

      lcd.print(“Plug2 Off”);

      lcd.setCursor(0,3);

      lcd.print(“Plug3 Off”);

    }

    HTTP_req=””;

  }

}

Programul a fost dezvoltat și testat cu Arduino IDE 1.8.1 și bibliotecile rc-switch 2.6.2, Ethernet2 1.0.4 și LiquidTWI 1.5.1.

Ne-conectarea LCD-ului (neutilizarea acestuia) nu afectează în nici un fel funcționalitatea web a sistemului. Interfața web de comandă se va accesa din aceiași rețea locală cu sistemul de comandă utilizând un client web și accesând adresa de IP a sistemului. LCD-ul nu face altceva decât să reflecte comenzile radio transmise prin intermediul interfeței web:

6

Comunicația între sistemul de comandă și prize este unidirecțională. Sistemul nu poate determina starea unei prize ci poate doar să transmită o comandă către aceasta – LCD-ul nu afișează starea prizelor ci ultima comandă transmisă, dacă starea prizei este modificată manual (din buton) sau din telecomandă acest lucru nu se va reflecta în informația afișată.

Seria de dispozitive de automatizare a locuinței Conrad RSL este compusă din dispozitive telecomandate radio perfect compatibile între ele. În cadrul sistemului de comandă construit se pot adăuga și alte elemente telecomandate din această serie. Codurile transmise de sistemul de comandă trebuie doar înregistrate în noile dispozitive adăugate. Vă recomandăm și priza intermediară de exterior (protecție IP44, funcționare identică cu a celor din setul de prize intermediare prezentat, memorie 10 coduri de comandă, 2000W, recepție comandă până la 70m):

 

7

 

 

Proiect WiFi Car Revolutions (partea a II-a)

Recunoașterea limbajului natural a devenit încet, încet o funcție obișnuită prin care putem comanda diverse dispozitive inteligente precum telefonul mobil sau calculatorul de bord al automobilul personal. Este posibil să implementăm o funcționalitate asemănătoare pentru WiFi Car? Este posibil să revoluționăm telecomenzile RC uzuale și să adăugăm comandă prin limbaj natural? Da!

2

Pentru a face acest lucru vom exploata conexiunea de rețea, prezentată în prima parte, pentru a conecta WiFi Car la un serviciu cloud de recunoaștere vocală. Puterea de calcul a plăcii de dezvoltare nu permite implementarea algoritmului de recunoaștere vocală local, pe placa de dezvoltare a WiFi Car, din această cauză vom apela la resursele de calcul a unui sistem de cloud. Sistemul de cloud utilizat este IBM BlueMixTM, serviciu cloud comercial dar cu posibilitatea de evaluare gratuită de 30 de zile fără a fi nevoie să introducem informații legate de un card bancar. Mai mult decât atât, în anumite centre universitare din țară accesul studenților și profesorilor este gratuit nelimitat. Pentru familiarizarea cu serviciul de cloud IBM BlueMixTM se poate revedea și lecția How sunny is the Blue? (I, II). Înregistrarea pe platformă se face la adresa:

Sign up for IBM Bluemix

https://console.ng.bluemix.net/registration/

După înregistrare și conectare la platformă se va naviga în zona de aplicații și se va crea o aplicație nouă (Create Application) de tipul Boilerplates / Internet of Things Platform Starter:

3

Se va alege un nume pentru aplicație (în cadrul lecției se va utiliza numele WCR dar puteți alege orice alt nume) și se va da comanda (Create) de alocare de resurse cloud pentru această aplicație nouă. Alocarea de resurse poate dura câteva minute sau zeci de minute. Finalizarea operației este marcată de schimbarea stării aplicației în Running.

4

În plus, trebuie să adăugm aplicației noastre un serviciu de tip Speech to Text (serviciul de recunoaștere vocală): Services /  Watson / Speech to Text. Noul serviciu trebuie asociat cu aplicația creată anterior (Conections / Create connection):

5

După definirea conexiunii aplicația WCR se va restarta. Pentru a putea conecta WiFi Car la aplicația nou creată trebuie să mergem în Dashboard-ul de administrare a serviciului WCR-iotf-service (Connect your devices / Launch dashboard). Comanda ne va direcționa către portalul IBM Watson IoT Platform unde vom crea un nou dispozitiv (Devices / Add Device). Nu trebuie să completăm decât tipul dipozitivului (în exemplul nostru Adafruit_HUZZAH) și numele dispozitivului (în exemplul nostru WCR). La finalizarea adăugării noului dispozitiv trebuie să notăm informațiile de autentificare furnizate de platformă pentru a putea să le folosim în programul dispozitivului (Organization ID, Device Type, Device ID, Authentication Method și Authentication Token).

6

Următorul pas este scrierea aplicație Node-RED care va face conversia între comenzile vocale date de utilizator și comenzile WiFi Car. Vom naviga la adresa https://wcr.mybluemix.net/ (adresa diferă în funcție de numele ales al aplicației) și vom accesa Node-RED flow editor (editorul vizual ce ne va permite scrierea aplicației). Aplicația are diagrama următoarea:

7

Pentru a putea utiliza elementul de intrare de tip microfon trebuie să instalăm următoarele două extensii Node-RED: node-red-contrib-browser-utils și node-red-contrib-media-utils (extensiile se instalează accesând din meniul principal opțiunea Manage palette). Elementul de intrare de tip microphone va permite înregistrea comenzilor vocale direct din browser și le va transmite automat către serviciul de recunoaștere vocală Speach to Text. Ieșirea serviciului de recunoaștere vocală se va conecta la un bloc decizional cu următoarea configurație:

8

Rolul blocului decizional este de a identifica comenzile vocale transcrise de serviciul de recunoaștere vocală (forward, backward, stop, left, right). Din păcate serviciul de recunoaștere vocală nu este disponibil în limba română. Ieșirile blocului decizional conduc la blocuri distincte de construire a comenzii în format JSON către serviciul IoT:

9

Serviciul IoT care va trimite, prin intermediul serviciului IBM Watson, comenzile către WiFi Car va avea următoarea configurație:

10

Pentru siguranță am adăugat un bloc de intrare pentru comanda de STOP care permite comanda manuală pentru cazuri de urgență. Restul componentelor din aplicație sunt utile doar pentru depanare: blocul msg.transcription va afișa textul de ieșire al serviciului de recunoaștere vocală iar blocurile WCR + msg.payload ne arată mesajele ce ajung efectiv la serviciul IoT.

Ultimul pas al implementării este reprogramarea modulului Adafruit HUZZAH pentru a prelua comenzile de la serviciul IBM Watson (pentru reprogramare modulul trebuie deconectat de la placa Arduino Uno). Programul a fost dezvoltat și testat utilizând Arduino IDE 1.8.1 și extensia esp8266 2.3.0 precum și bibliotecile MQTT 1.11.0 și ArduinoJson 5.8.3.

#include <ESP8266WiFi.h>

#include <MQTTClient.h>

#include <ArduinoJson.h>

 

Programul trebuie particularizat cu datele de conectare la rețeaua WiFi locală (ssid și password) precum și cu datele de autentificare la serviciul de cloud (OrgID, DeviceT, DeviceID, AuthenticationToken și OrgID):

const char* ssid     =  ““;

const char* password =  ““;

WiFiClient net;

MQTTClient client;

void connect_mqtt() {

while (!client.connect(“d:OrgID:DeviceT:DeviceID“, “use-token-auth”,”AuthenticationToken“)) {

delay(1000);

}

client.subscribe(“iot-2/cmd/+/fmt/json”);

}

void setup() {

Serial.begin(9600);

delay(10);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {

delay(500); }

client.begin(“OrgID.messaging.internetofthings. ibmcloud.com”, 1883, net);

connect_mqtt();

}

void loop() {

client.loop();

delay(10);

if (!client.connected()) { connect_mqtt(); }

}

void messageReceived(String topic, String payload, char * bytes, unsigned int length) {

StaticJsonBuffer jsonBuffer;

JsonObject& root = jsonBuffer.parseObject(payload);

if (!root.success()) {

return;

}

String command = root[“command”];

Serial.println(command);

}

Programul de pe placa Arduino Uno rămâne neschimbat. După reconectarea modulului Adafruit HUZZAH la WiFi Car putem să testăm comanda vocală. Din aplicația Node-RED se apasă butonul blocului microphone și se dă comanda (se înregistrează o comandă vocală care să conțină unul dintre cuvintele cheie forward, backward, stop, left sau right). Atenție, trebuie să permitem la nivel de browser ca aplicația Node-RED să acceseze dispozitivul hardware microfon al sistemului de calcul. După rostirea comenzii se apasă din nou butonul blocului microphone pentru a opri înregistrarea și a trimite comanda vocală către serviciul de recunoaștere vocală.

11

În captura de ecran anterioară se pot vedea mesajele din consola debug pentru o comandă vocală (right) și o comandă manuală (stop). Pentru comanda vocală se poate vedea atât recunoașterea vocală a comenzii cât și mesajul obținut ca feedback de la serviciul IoT. Pentru comanda manuală avem doar feedback-ul afișat.

Bineînțeles, ca alternativă la comanda vocală din browser există posibilitatea construirii unui sistem portabil de înregistrare vocală (telecomandă vocală). Proiectul de mai jos explorează această posibilitate utilizând o placă de dezvoltare Raspberry Pi:

Control your Robosapien Humanoid Robot using IBM Watson IoT Platform, Raspberry Pi and Node-RED (Part 1)

https://developer.ibm.com/recipes/tutorials/control-your-robosapien-humanoid-robot-using-ibm-watson-iot-platform-raspberry-pi-and-nodered/

Control the Humanoid Robot with voice commands using IBM Watson Speech to Text service (Part 2)

https://developer.ibm.com/recipes/tutorials/control-the-humanoid-robot-with-voice-commands-using-ibm-watson-speech-to-text-service-part-2/

Proiect WiFi Car Revolutions (partea I)

La fel ca și în cazul filmelor de succes, reluarea repetată a unei idei este destul de periculoasă din cauza epuizării rând pe rând a variantelor interesante ce pot capta atenția. Totuși, în cadrul proiectului de față vom relua problematica realizării unei platforme robotice comandate prin WiFi sperând să vă păstrăm în continuarea atenția și interesul prin propunerea unei soluții ”revoluționare” atât ca și componente hardware utilizate cât și ca modalitate de comandă.

Platforma robotică propusă se bazează pe aceiași platformă FlexyBot utilizată și în precedentele două WiFi Car (WiFi Car și WiFi Car Reloaded). Se poate utiliza atât varianta cu două motoare cât și varianta cu patru motoare (comandă unificată pentru motoarele de pe aceiași parte a platformei).

2

Pentru implementarea comenzii vom utiliza o soluție clasică: placă de dezvoltare Arduino Uno R3 și shield driver de motoare L298 (shield utilizat și în prima versiune a WiFi Car). Pentru a realiza conexiunea WiFi vom utiliza o componentă Adafruit HUZZAH ESP8266 ce permite o conversie între comunicația de rețea WiFi și comunicația serială.

3

Noua soluție de implementare a comenzii are următoarele avantaje:

  • Un cost mai mic (placa de dezvoltare Arduino Uno + modulul Adafruit HUZZAH sunt mai ieftine împreună decât placa de dezvoltare Arduino Yun);
  • Se poate implementa o alimentare comună, placa de dezvoltare se poate alimenta direct prin intermediul shield-ului de motoare – se poate utiliza o singură sursă de alimentare de 7.4V (accumulator LiPo cu două celule) sau 9V (cutie 6 baterii AA) direct pe pinii de alimentare a shieldului cu jumperul de alimentare pus;

4

  • Soluția este extrem de familiară fiind similară cu soluția propusă de kit-ul FlexyBot Doua Motoare Controlat prin Bluetooth – doar se înlocuiește modulul bluetooth cu cel WiFi – conectorul este compatibil cu noul modul fiind vorba tot de comunicație serială. Aveți grijă să potriviți pinul de GND al modulului cu pinul de GND al conectorului de pe shield.

5

 

Înainte de montarea modulului WiFi pe shield el trebuie programat, după montare nu mai este posibilă programarea deoarece pinii de programare sunt utilizați pentru comunicația serială cu placa Arduino Uno.

Pentru programarea și utilizarea modulului Adafruit HUZZAH este necesată parcurgerea materialului următor:

Adafruit HUZZAH ESP8266 breakout

https://learn.adafruit.com/adafruit-huzzah-esp8266-breakout

Programul ce va rula pe modulul Adafruit este derivat din exemplul WiFiTelnetToSerial al extensiei esp8266 pentru Arduino IDE (codul a fost testat utilizând Arduino IDE 1.8.1 și extensia esp8266 2.3.0):

#include <ESP8266WiFi.h>

#define MAX_SRV_CLIENTS 1

const char* ssid = ““;

const char* password = ““;

WiFiServer server(23);

WiFiClient serverClients[MAX_SRV_CLIENTS];

void setup() {

  Serial.begin(9600);

  Serial.println();

  WiFi.begin(ssid, password);

  uint8_t i = 0;

  while (WiFi.status() != WL_CONNECTED && i++ < 20)

delay(500);

  if(i == 21){ while(1) delay(500); }

   server.setNoDelay(true); }

 

void loop() {

  uint8_t i;

  if (server.hasClient()){

    for(i = 0; i < MAX_SRV_CLIENTS; i++){

      if (!serverClients[i] ||

                      !serverClients[i].connected()){

        if(serverClients[i]) serverClients[i].stop();

        serverClients[i] = server.available();

        serverClients[i].println(F(“=== WiFi Car Revolutions ===”));

        continue;

      }

    }

    WiFiClient serverClient = server.available();

    serverClient.stop();

  }

  for(i = 0; i < MAX_SRV_CLIENTS; i++){

    if (serverClients[i] && serverClients[i].connected()){

      if(serverClients[i].available()){

        while(serverClients[i].available())

Serial.write(serverClients[i].read()); }

    }

  }

  if(Serial.available()){

    size_t len = Serial.available();

    uint8_t sbuf[len];

    Serial.readBytes(sbuf, len);

    for(i = 0; i < MAX_SRV_CLIENTS; i++){

      if (serverClients[i] &&

                      serverClients[i].connected()){

        serverClients[i].write(sbuf, len);

        delay(1);  }

    }

  }

}

Pentru încărcarea codului se va utiliza un cablu USB to TTL sau un conector FTDI. Modulul WiFi va încerca conectarea într-o rețea WiFi locală ce oferă IP-ul dinamic prin DHCP – credențialele de conectare (ssid și password) trebuie personalizate în program.

După programarea modulului WiFi el poate fi conectat la platforma mobilă și se poate trece la programarea plăcii Arduino Uno. Codul pentru componenta Arduino este similar cu codul utilizat în cadrul variantei WiFi Car Reloaded pentru componenta 32U4 – programul va avea rolul de a transpune comenzile primite serial în comenzi către motoare (apar deosebiri la pinii de comandă ai motoarelor și la portul serial folosit, în cazul de față vom utiliza un port serial software – toate specifice shield-ului de motoare folosit).

#define MOTOR2_PIN1 3

#define MOTOR2_PIN2 5

#define MOTOR1_PIN1 6

#define MOTOR1_PIN2 9

#include “SoftwareSerial.h”

SoftwareSerial mySerial(2,4);

int vs = 0;

int vd = 0;

void setup()

{ mySerial.begin(9600);

  pinMode(MOTOR1_PIN1, OUTPUT);

  pinMode(MOTOR1_PIN2, OUTPUT);

  pinMode(MOTOR2_PIN1, OUTPUT);

  pinMode(MOTOR2_PIN2, OUTPUT); }

 

void loop()

{ if (mySerial.available()) {

    char c = (char)mySerial.read();

    switch (c) {

      case ‘i’:

        if (vs<245) vs=vs+10;

        if (vd<245) vd=vd+10;

        mySerial.print(“Viteza: “);

        mySerial.print(vs);

        mySerial.print(“/”);

        mySerial.println(vd);

        break;

      case ‘b’:

        if (vs>-245) vs=vs-10;

        if (vd>-245) vd=vd-10;

        mySerial.print(“Viteza: “);

        mySerial.print(vs);

        mySerial.print(“/”);

        mySerial.println(vd);

        break;

      case ‘s’:

        if (vs<245) vs=vs+10;

        if (vd>-245) vd=vd-10;

        mySerial.print(“Viteza: “);

        mySerial.print(vs);

        mySerial.print(“/”);

        mySerial.println(vd);

        break;

      case ‘d’:

        if (vs>-245) vs=vs-10;

        if (vd<245) vd=vd+10;

        mySerial.print(“Viteza: “);

        mySerial.print(vs);

        mySerial.print(“/”);

        mySerial.println(vd);

        break;       

      case ‘x’:

        vs=0;

        vd=0;

        mySerial.print(“Viteza: “);

        mySerial.print(vs);

        mySerial.print(“/”);

        mySerial.println(vd);

        break;

    }

  }

  mySerial.flush();

  go(vs,vd);

  delay(50);

}

 

void go(int speedLeft, int speedRight) {

  if (speedLeft > 0) {

    analogWrite(MOTOR1_PIN1, speedLeft);

    analogWrite(MOTOR1_PIN2, 0);

  }

  else {

    analogWrite(MOTOR1_PIN1, 0);

    analogWrite(MOTOR1_PIN2, -speedLeft);

  }

  if (speedRight > 0) {

    analogWrite(MOTOR2_PIN1, speedRight);

    analogWrite(MOTOR2_PIN2, 0);

  }else {

    analogWrite(MOTOR2_PIN1, 0);

    analogWrite(MOTOR2_PIN2, -speedRight);

  }

}

Comanda platformei robotice rezultate se poate face, la fel ca și în cazul WiFi Car Reloaded,  utilizând un client telnet (adresa de conectare este adresa IP alocată modulului WiFi prin DHCP) și comenzile i, d, s, b, x:

6

Sau utilizând aplicația Android RoboRemoFree – Arduino control:

7

https://play.google.com/store/apps/details?id=com.hardcodedjoy.roboremofree

și configurând o interfață cu cinci butoane pentru comenzile i, d, s, b, x.

8

Adresa de conectare va fi adresa IP a sistemului și portul va fi portul 23 (specific protocolului telnet):

9

 

 

 

 

Proiect WiFi Car Reloaded (partea a II-a)

Adăugarea unei camere video la o platformă mobilă (mașină teleghidată) oferă posibilitatea extinderii funcționalității exploratorii – utilizatorul va putea să controleze la distanță platforma mobilă văzând efectiv mediul în care aceasta se mișcă. Această facilitate este folosită uzual la roboții teleghidați ce explorează medii periculoase (roboți de deminare de exemplu) sau medii inaccesibile omului. WiFi Car Reloaded își propune adăugarea acestei funcționalități pentru a crește cazurile de utilizare posibile.

Pentru a nu crește costul sistemului vom utiliza o cameră web USB obișnuită dar se poate modifica foarte ușor proiectul pentru a utiliza o cameră serială de exemplu. Calitatea camerei web va da performanțele de achiziție a imaginilor pentru sistem. Conectarea unei camere web USB la un sistem ce rulează OpenWRT a fost explicată în lecția ”Ce putem face cu o cameră web veche?” dar vom relua pe scurt elementele principale ale configurației în cele ce urmează.

Conectarea unei camere web USB la placa LinkIt Smart 7688 Duo necesită un adaptor OTG (imagine de mai jos).

2

După conectarea fizică a camerei trebuie să verificăm recunoașterea corectă a dispozitivului USB de către sistemul de operare, se face cu ajutorul următoarelor comenzi (în consola OpenWRT):

dmesg – va afișa mesajele generate de nucleu sistemului de operare la conectarea dispozitivului USB;

3

lsusb – va enumera dispozitivele USB conectate;

4

lsusb -s 001:002 -v | egrep “Width|Height” – ne permite identificarea modurilor video – rezoluțiilor – suportate;

5

ls /dev/video* –  va enumera dispozitivele video din sistem.

6

În cazul în care una dintre comenzile prezentate nu este recunoscută sau camera video nu este recunoscută ca dispozitiv USB sau video se va verifica dacă pachetele software necesare sunt instalate:

opkg update 

opkg install kmod-video-uvc kmod-video-core

opkg install usbutils

opkg install mjpg-streamer

Pentru transmisia live de imagine se va utiliza programul mjpg-streamer (instalat de ultima comandă din blocul anterior). Comanda de pornire a acestuia este:

mjpg_streamer -i “input_uvc.so -d /dev/video0 -y” -o “output_http.so”

Accesarea imaginilor transmise se poate face la adresele:

Flux video:

http://adresa_IP_sistem:8080/?action=stream

Imagini:

http://adresa_IP_sistem:8080/?action=snapshot

Pentru ca aplicația mjpg-streamer să pornească în mod automat trebuie ca în fișierul /etc/config/mjpg_streamer să configurați parametrul enabled (și alți parametrii dacă este cazul):

config mjpg-streamer ‘core’

        option enabled ‘1’

        option input ‘uvc’

        option output ‘http’

        option device ‘/dev/video0’

#       option resolution ‘320×240’

        option yuv ‘1’

        option quality ’80’

        option fps ’15’

#       option led ‘auto’

#       option www ‘/www/webcam’

        option port ‘8080’

#       option username ‘openwrt’

#       option password ‘openwrt’

și să executați comanda:

/etc/init.d/mjpg-streamer enable

Pentru mai multe informații despre configurarea programului mjpg-streamer puteți consulta materialul:

Webcam with the Linux UVC driver [OpenWrt Wiki]

https://wiki.openwrt.org/doc/howto/webcam

În acest moment mașina emite imagini live și poate fi comandată simultan prin WiFi. Pentru vizualizarea imaginilor se poate utiliza un client web (browser) sau o aplicație multimedia (VLC de exemplu – captura de ecran de mai jos).

7

Pentru a putea realiza o comandă mai bună a platformei robotice vom înlocui clientul telnet utilizat până acum cu o aplicație mobilă pentru dispozitivele Android: RoboRemoFree – Arduino control:

8

https://play.google.com/store/apps/details?id=com.hardcodedjoy.roboremofree

Această aplicație a fost creată pentru proiecte bazate pe platforma Arduino și module de comunicație bluetooth  sau pentru platforme bazate pe circuitul WiFi ESP8266 dar noi o vom putea utiliza fără probleme pentru platforma noastră. Mai multe despre proiectul Robo Remo puteți găsi la adresa:

RoboRemo – Customizable Bluetooth / Internet / WiFi Remote Control App

http://www.roboremo.com/

Pentru configurarea aplicației mobile trebuie să edităm interfața utilizator (edit ui) și să adăugăm cinci controale de tip buton pe care definim acțiunile (set press action): i, d, s, b, x. După finalizarea interfeței ne vom conecta prin rețea (Internet (TCP)) la adresa adresa_ip_sistem:2001 . În acest moment mașina poate fi comandată prin intermediul aplicației mobile iar timpul de reacție este mult mai bun față de varianta prin intermediul protocolului HTTP.

10

9

 

Un ultim sfat: pentru a scădea încărcarea sistemului OpenWRT puteți activa doar comunicația între portul 2001 și a portului serial /dev/ttyS0 . În fișierul /etc/ser2net.conf se vor comenta toate liniile de după linia ce definește comunicația utilizată:

2001:raw:600:/dev/ttyS0:9600 NONE 1STOPBIT 8DATABITS XONXOFF LOCAL -RTSCTS

#2002:raw:600:/dev/ttyS1:9600 NONE 1STOPBIT 8DATABITS XONXOFF LOCAL -RTSCTS

#2003:raw:5:/dev/ttyS2:9600

#2004:raw:5:/dev/ttyS3:115200

 

 

Dacă sunteți în căutare de idei suplimentare vă recomandăm și următoarele proiecte:

Wi-Fi RC Car – Qi Enabled – Arduino Project Hub

https://create.arduino.cc/projecthub/ioanniskydonis/wi-fi-rc-car-qi-enabled-b972b2

WiFi Controlled Mobile Robot | Adafruit Learning System

https://learn.adafruit.com/wifi-controlled-mobile-robot/

Arduino RC Car With FPV Camera

http://www.instructables.com/id/Arduino-RC-Car-with-FPV-Camera/

Make a remote tank with LinkIt smart 7688 Duo and MCS gamepad channel

https://iamblue.gitbooks.io/linkit-smart-nodejs/content/en/cloud/gamepad.html

arduino WiFi remote control car – WiFi arduiCar

http://wiznetmuseum.com/portfolio-items/arduino-wifi-remote-control-car-wifi-arduicar/

Lukse.lt » Carambola powered robot v2

http://lukse.lt/uzrasai/2013-01-carambola-powered-robot-v2/

Proiect WiFi Car Reloaded (partea I)

Așa cum am prezentat și în proiectul precedent (WiFi Car), realizarea unei platforme robotice comandate la distanță prin intermediul unei conexiuni WiFi se poate realiza foarte simplu prin intermediul unei plăci de dezvoltare mixte (microprocesor + microcontroler) – Arduino Yun sau echivalentă. În cadrul lecției de față vom relua aceiași provocare dar vom aduce o serie de îmbunătățiri atât la nivel hardware cât și la nivel funcțional.

1

Din punct de vedere hardware ne propunem să utilizăm o placă de dezvoltare similară cu placa Arduino Yun dar de dimensiuni mult mai mici, în plus nu vom mai utiliza un șasiu cu 2 motoare ci unul cu 4 motoare pentru o stabilitate crescută și o manevrabilitate mult mai bună. Din punct de vedere funcțional vom adăuga posibilitatea de control prin intermediul unei aplicații mobile și transmiterea de imagini live direct de pe platforma robotică (vom adăuga o cameră ce va transmite de pe WiFi Car).

Șasiul utilizat pentru implementare este asemănător cu cel folosit anterior dar dispune de 4 roți și 4 motoare oferind, în ciuda unui consum mai mare, o stabilitate foarte bună și o posibilitate de control al direcției superioară variantei cu doar 2 motoare:

2

https://www.robofun.ro/kit-roboti/flexybot-4-motoare

Placa de dezvoltare utilizată este o placă MediaTek LinkIt Smart 7688 Duo, placă cu aceleași facilități funcționale și performanțe ca și placa de dezvoltare de Arduin Yun dar la un preț și o dimensiune mult mai mici:

3

https://www.robofun.ro/wireless/wireless-wifi/linkit-smart-7688-duo

Pentru controlul motoarelor vom utiliza un driver dual de curent Pololu DRV8835 ce permite o logică de comandă între 2V și 7V și o tensiune de comandă de pănă la 11V și 1.2A per canal (potrivit pentru mașina noastra ce va avea o logică de comandă de 3.3V și o tensiune de alimentare a motoarelor de 7.4V și un curent de 2x300mA per canal):

4

https://www.robofun.ro/mecanice/driver/driver_dc/drv8835-dual-motor-driver

5

Alimentarea mașinii se va face prin intermediul unui accumulator LiPo de 7.4V și capacitate 1800mAh dar dacă se dorește o autonomie mai mare se poate înlocui varianta indicată cu un accumulator de capacitate mai mare. Atenție!!! Utilizarea accumulatorilor LiPo necesită anumite precauții specifice (pericol de explozie / incendiu). Pentru începători este recomandată utilizarea unei cutii de 6 baterii AA – la fel ca și în lecția precedentă – conectarea este identică atât pentru accumulatorul LiPo cât și pentru cutia de baterii.

https://www.robofun.ro/surse_de_alimentare/acumulatori/acumulator-lipo-gens-1800mah

Tensiunea oferită de accumulator va alimenta în mod direct motoarele prin intermediul driverului de curent dar pentru alimentarea plăcii de dezvoltare, deoarece nu există regulator de tensiune pe placă, este nevoie de un regulator step-down de 5V extern, de exemplu:

6

https://www.robofun.ro/surse_de_alimentare/regulator_step_down/pololu-5v-1a-step-down-voltage-regulator-d24v10f5

Astfel, sistemul de alimentare al mașinii are următoarea schemă (este inclus și un întrerupător pentru oprirea alimentării, este util dar opțional):

7

Schema de interconectare a componentelor de comandă este următoarea:

8

După cum se poate vedea din schema de interconectare, placa de dezvoltare se va alimenta la 5V (ieșirea regulatorului de tensiune) iar motoarele (prin intermediul driverului de curent) la 7.4V/9V. Placa de dezvoltare dispune totuși de un regulator de tensiune intern ce coboară tensiunea de la 5V la 3.3V, ieșirea de 3.3V va fi utilizată pentru a indica driverului de curent nivelul tensiunii de comandă (spre deosebire de placa Arduino Yun care avea logica pinilor pe 5V, placa LinkIt Smart 7688 Duo are logica pinilor pe 3.3V). La ieșirea driverului de curent se vor conecta câte două motoare pe fiecare canal (cele din dreapta pe un canal, cele din stânga pe celălalt canal).

Comanda individuală a celor patru motoare nu este necesară deoarece controlul direcției se poate face foarte bine și prin comanda simultană a motoarelor de pe aceiași parte. Placa va comanda motoarele de pe partea stângă prin intermediul pinilor digitali 5 și 6 iar motoarele de pe partea dreaptă prin intermediul pinilor digitali 9 și 10 (toți cei patru pini au facilitate de ieșire PWM). Dacă, la punerea în funcțiune a mașinii, se observă anomalii de tipul: motoarele de pe aceiași parte se rotesc în sens invers sau în loc ca mașina să meargă înainte se rotește înseamnă că motoarele au fost conectate încrucișat și trebuie modificată conectarea acestora.

Noua platformă WiFi Car (Reloaded) poate fi programată în mod similar cu vechea platformă WiFi Car (placa LinkIt Smart 7688 Duo are aproape aceiași arhitectură cu placa Arduino Yun și rulează tot sistemul de operare OpenWRT) – singura modificare necesară este schimbarea definițiilor de conectare a pinilor de comandă.

Nu vom continua dezvoltarea programului din proiectul precedent ci vom propune o nouă abordare în comanda la distanță a WiFi Car. Noul sistem software va avea două componente: o componentă ce va rula pe microprocesorul plăcii (sub OpenWRT) și se va ocupa de retransmiterea traficului de rețea către portul serial al microcontrolerului și o componentă ce va rula pe microcontrolerul ATmega32U4 și se va ocupa cu comanda motoarelor conform mesajelor primite pe serială (similar cu funcționarea unei mașini comandate prin bluetooth).

Programul ce va rula pe microcontrolerul ATmega32U4 este următorul (programarea plăcii se poate face, la fel ca și în cazul plăcii Arduino Yun, prin WiFi – Over The Air):

#define MOTOR2_PIN1 10

#define MOTOR2_PIN2 9

#define MOTOR1_PIN1 6

#define MOTOR1_PIN2 5

int vs = 0;

int vd = 0;

void setup() {

  pinMode(MOTOR1_PIN1, OUTPUT);

  pinMode(MOTOR1_PIN2, OUTPUT);

  pinMode(MOTOR2_PIN1, OUTPUT);

  pinMode(MOTOR2_PIN2, OUTPUT);

  Serial1.begin(9600); }

void loop() { 

  if (Serial1.available()) {

    char c = (char)Serial1.read();

    switch (c) {

      case ‘i’:

        if (vs<245) vs=vs+10;

        if (vd<245) vd=vd+10;

        Serial1.print(“Viteza: “);

        Serial1.print(vs);

        Serial1.print(“/”);

        Serial1.println(vd);

        break;

      case ‘b’:

        if (vs>-245) vs=vs-10;

        if (vd>-245) vd=vd-10;

        Serial1.print(“Viteza: “);

        Serial1.print(vs);

        Serial1.print(“/”);

        Serial1.println(vd);

        break;

      case ‘s’:

        if (vs<245) vs=vs+10;

        if (vd>-245) vd=vd-10;

        Serial1.print(“Viteza: “);

        Serial1.print(vs);

        Serial1.print(“/”);

        Serial1.println(vd);

        break;

      case ‘d’:

        if (vs>-245) vs=vs-10;

        if (vd<245) vd=vd+10;

        Serial1.print(“Viteza: “);

        Serial1.print(vs);

        Serial1.print(“/”);

        Serial1.println(vd);

        break;       

      case ‘x’:

        vs=0;

        vd=0;

        Serial1.print(“Viteza: “);

        Serial1.print(vs);

        Serial1.print(“/”);

        Serial1.println(vd);

        break;

    }

  }

  Serial1.flush();

  go(vs,vd);

  delay(50);

}

void go(int speedLeft, int speedRight) {

  if (speedLeft > 0) {

    analogWrite(MOTOR1_PIN1, speedLeft);

    analogWrite(MOTOR1_PIN2, 0);

  }

  else {

    analogWrite(MOTOR1_PIN1, 0);

    analogWrite(MOTOR1_PIN2, -speedLeft);

  }

  if (speedRight > 0) {

    analogWrite(MOTOR2_PIN1, speedRight);

    analogWrite(MOTOR2_PIN2, 0);

  }else {

    analogWrite(MOTOR2_PIN1, 0);

    analogWrite(MOTOR2_PIN2, -speedRight);

  }

}

Se observă că programul preia de pe portul serial Serial1 (portul serial ce face legătura între microprocesor și microcontroler) comenzile de înainte (i), dreapta (d), stânga (s), înapoi (b) și stop (x) și le transmite către motoare. Comenzile constau în modificarea (incrementarea sau decrementarea cu 10) celor două viteze (a motoarelor de pe partea dreapta și a motoarelor de pe partea stângă).

Înainte de a implementa cea de a doua componentă software a sistemului, componenta de legătură între conexiunea WiFi și comunicația serială dintre cele două circuite programabile ale plăcii de dezvoltare, trebuie să configurăm placa LinkIt Smart 7688 Duo să poată acceseze Internet prin intermediul unei rețele WiFi locale – configurația inițială a plăcii – similară cu partea de configurare inițială din lecția precedentă. Pentru configurarea de bază / inițială a plăcii de dezvoltare LinkIt Smart 7688 Duo se poate consulta următorul material:

LinkIt Smart 7688 Duo – Seeed Wiki

http://wiki.seeed.cc/LinkIt_Smart_7688_Duo/

Testarea configurației următoare a fost realizată pe o placă LinkIt Smart 7688 Duo cu firmware 0.9.4.

Componenta software ce va rula pe microprocesorul sistemului sub OpenWRT este aplicația ser2net ce trebuie instalată:

opkg update

opkg install ser2net

Pentru pornirea automată a aplicației la restarea sistemului vom crea fișierul /etc/init.d/ser2net cu următorul conținut:

#!/bin/sh /etc/rc.common

START=10

STOP=15

start(){

ser2net

}

stop(){

killall ser2net

}

După care vom activa pornirea aplicației și vom porni efectiv aplicația:

chmod +x /etc/init.d/ser2net

/etc/init.d/ser2net enable

/etc/init.d/ser2net start

Pentru a transmite comenzile către mașină vom utiliza o aplicație client telnet (putty de exemplu) și ne vom conecta la adresa IP locală a plăcii de dezvoltare pe portul 2001. În consola telnet vom trimite comenzile descrise anterior (caracterele i, s, d, b, x) – captură de ecran de mai jos.

9

În partea a doua a proiectului vom vedea cum putem realiza comanda prin intermediul unei aplicații mobile și, bineînțeles, cum putem adăuga sistemului nostru o cameră video.

Proiect WiFi Car

Realizarea unei mașini teleghidate este o provocare plăcută pentru orice pasionat de electronică indiferent dacă este începător sau veteran. Dacă soluțiile clasice RC bazate pe frecvențe subgigahertz sau bazate pe protocolul bluetooth sunt exemplificate într-o multitudine de proiecte, varianta de comandă radio prin protocol WiFi este puțin mai problematică din cauza consumului și costurilor mari pentru componenta de comunicație. În cadrul proiectului de față vom prezenta o soluție simplă de realizarea a unei mașini controlate prin WiFi bazându-ne pe următoarele componente:

  1. Un șasiu FlexyBot cu cu două motoare:

2

https://www.robofun.ro/kit-roboti/flexy-bot-2-motoare

  1. O placă de dezvoltare Arduino Yun ce va asigura atât partea de logică de comandă cât și partea de comunicație WiFi:

3https://www.robofun.ro/wireless/wireless-wifi/arduino_yun

  1. Un shield driver de motoare bazat pe circuitul L298:

4

https://www.robofun.ro/shields/shield-motoare-l298-v2

Asamblarea celor trei componente este simplă și este prezentată detaliat în pagina produsului FlexyBot. Nu există deosibiri majore între placa Arduino Uno și placa Arduino Yun în această fază. Nu alimentați ansamblul până nu parcurgeți următorii pași ai lecției (Configurarea inițială a plăcii Arduino Yun și Alimentarea WiFi Car).

Configurarea inițială a plăcii Arduino Yun

Configurarea inițială a plăcii Arduino Yun este prezentată în materialul:

Start with Arduino Yun

http://www.arduino.org/learning/getting-started/getting-started-with-arduino-yun

În funcție de modul în care doriți să interacționați cu WiFi Car există două posibile configurații WiFi:

  1. Să lăsați placa Arduino Yun configurată ca WiFi AP – configurație utilă dacă doriți să accesați WiFi Car și în afara acoperirii unei rețele WiFi cunoscute, vă veți conecta cu un dispozitiv de comandă la AP-ul WiFi Car.
  2. Să configurați placa Arduino Yun să se conecteze la o rețea WiFi – această configurația are avantajul de a oferi posibilă conectivitate Internet plăcii Arduino Yun dar este dependentă de aria de acoperire a rețelei WiFi prin care se va face comanda la distanță.

Indiferent de varianta aleasă, utilizarea plăcii Arduino Yun oferă marele avantaj al posibilității programării la distanță a WiFi Car – nu trebuie să conectați, deconectați, reconectați cablul USB la fiecare nouă testare de program. Totul se poate face la distanță prin selectarea portului OTA (Over-The-Air).

5

 

Alimentarea WiFi Car

Pentru alimentarea WiFi Car se vor folosi două elemente distincte: o cutie de baterii ce va alimenta motoarele prin intermediul shield-ului și o baterie USB pentru a alimenta placa Arduino Yun. În cadrul testelor s-a utilizat o cutie cu 6 baterii AA și un USB Battery Pack de 2000mAh.

6

https://www.robofun.ro/surse_de_alimentare/baterii/cutie-6-baterii-cablu

7

https://www.robofun.ro/surse_de_alimentare/acumulatori/usb-battery-pack-2200-mah-capacity-5v-1a-output

Cele două surse de alimentare distincte oferă o mai mare stabilitate plăcii de comandă Arduino Yun neproducând fluctuații ale tensiunii de alimentare la manevrele de pornire / oprire a motoarelor. În plus de asta, placa Arduino Yun nu are regulator de tensiune integrat (cum are placa Arduino Uno) și din acest motiv trebuie alimentată cu o tensiune de fix 5V.

ATENȚIE!!! Conectarea jumperului de pe shield-ul driver de motoare ce permite alimentarea plăcii de dezvoltare din aceiași sursă ca motoarele va conduce la arderea imediată a plăcii Arduino Yun deoarece aceasta nu acceptă pe pinul Vin altă tensiune decât fix 5V.

8

 

Programarea WiFi Car

Programul ce va rula pe microcontrolerul ATmega32U4 al plăcii Arduino Yun va utiliza biblioteca software Bridge pentru a crea legătura dintre comanda motoarelor și comenzile web pe care le vom trimite prin conexiunea WiFi.

#include <Bridge.h>

#include <BridgeServer.h>

#include <BridgeClient.h>

BridgeServer server;

Configurarea și comanda motoarelor este similară cu utilizarea shield-ului în conjuncție cu o conexiune bluetooth sau un algoritm local de tip evitare de obstacole sau urmărire de linie.

#define MOTOR2_PIN1 3

#define MOTOR2_PIN2 5

#define MOTOR1_PIN1 6

#define MOTOR1_PIN2 9

void setup() {

  Bridge.begin();

  pinMode(MOTOR1_PIN1, OUTPUT);

  pinMode(MOTOR1_PIN2, OUTPUT);

  pinMode(MOTOR2_PIN1, OUTPUT);

  pinMode(MOTOR2_PIN2, OUTPUT);

  server.listenOnLocalhost();

  server.begin();

}

void go(int speedLeft, int speedRight) {

  if (speedLeft > 0) {

    analogWrite(MOTOR1_PIN1, speedLeft);

    analogWrite(MOTOR1_PIN2, 0);

  } else {

    analogWrite(MOTOR1_PIN1, 0);

    analogWrite(MOTOR1_PIN2, -speedLeft);

  }

  if (speedRight > 0) {

    analogWrite(MOTOR2_PIN1, speedRight);

    analogWrite(MOTOR2_PIN2, 0);

  } else {

    analogWrite(MOTOR2_PIN1, 0);

    analogWrite(MOTOR2_PIN2, -speedRight);

  }

}

În cadrul secțiunii loop() se vor prelua, prin intermediul bibliotecii Bridge, conexiunile de comandă și se vor trimite către procedura process() pentru execuție.

void loop() { 

  BridgeClient client = server.accept();

  if (client) {

    process(client);

    client.stop();

  }

  delay(50);

}

void process(BridgeClient client) {

  String command = client.readStringUntil(‘/’);

  command.trim();

  if(command == “forward”) { 

          go(150,150);

          client.println(“Forward”);

          client.println(“Vs: 150 Vd: 150”);

        }

   if(command == “left”) { 

          go(100,150);

          client.println(“Left”);

          client.println(“Vs: 100 Vd: 150”);

        }

  if(command == “stop”) { 

          go(0,0);

          client.println(“Stop”);

        }

  if(command == “right”) { 

          go(150,100);

          client.println(“Right”);

          client.println(“Vs: 150 Vd: 100”);

        }

  if(command == “back”) { 

          go(-150,-150);

          client.println(“Backward”);

          client.println(“Vs: -150 Vd: -150”);

        }

}

După încărcarea programului se vor putea accesa comenzile WiFi Car de pe orice sistem ce deține un client web (browser) și este conectat la aceiași subrețea ca și placa Arduino Yun accesând următoarele URL-uri:

Pentru mers înainte

http://ip_placa_arduino_yun/arduino/forward/

Pentru virare stânga

http://ip_placa_arduino_yun/arduino/left/

Pentru virare dreapta

http://ip_placa_arduino_yun/arduino/right/

Pentru oprire

http://ip_placa_arduino_yun/arduino/stop/

Pentru mers înapoi

http://ip_placa_arduino_yun/arduino/back/

Bineînțeles, partea de comandă poate fi îmbunătățită prin introducerea unor comenzi de accelerare, frânare sau accentuare/încetinire a virării.

 

Realizarea unei interfețe centralizate de comandă

Având în vedere faptul că placa Arduino Yun rulează implicit un server web (uhttp) se poate realiza o pagină html care să centralizeze accesul la URL-urile de comandă. Există două variante de copiere și localizare la nivelul sistemului de fișiere OpenWRT a fișierului html:

 

Utilizarea unui card microSD și includerea fișierului html în proiectul Arduino. Copierea fișierului html se va face automat la încărcarea programului. Această variantă este descrisă în următorul material:

Arduino Yún: Intro to web server

https://create.arduino.cc/projecthub/Arduino_Scuola/arduino-yun-intro-to-web-server-6caf93

 

Crearea manuală a fișierului html în linie de comandă. Aceasta este varianta propusă datorită simplității.

Se va crea un fișier wificar.html în directorul /www cu următorul conținut:

<html>

<head>

<style>

a.button {-webkit-appearance: button;

-moz-appearance: button;

appearance: button;

height:200px;

line-height:200px;

text-align:center;

text-decoration: none;

font-size: 50px;

color: initial;}

</style>

</head>

<body>

<a href=”/arduino/forward/” class=”button”

style=”width:100%;””>FORWARDS</a>

<br />

<a href=”/arduino/left/” class=”button”

style=”width:35%;””>LEFT</a>

<a href=”/arduino/stop/” class=”button”

style=”width:30%;””>STOP</a>

<a href=”/arduino/right/” class=”button”

style=”width:35%;””>RIGHT</a>

<br />

<a href=”/arduino/back/” class=”button”

style=”width:100%;””>BACKWARDS</a>

<br />

</body>

</html>

Se va verifica dacă în fișierul /etc/config/uhttp variabila option home are valoarea /www:

# Server document root

option home             /www

Se va accesa URL-ul:

http://ip_placa_arduino_yun/wificar.html

9

Din păcate latența de comunicație a protocoalelor TCP/IP, mai ales al protocolului HTTP, este destul de mare. Nu vă așteptați să aveți aceiași viteză de răspuns ca în cazul unei mașini teleghidate RC obișnuite.