Using Bootstrap toolkit for Arduino based PLC's
developing with HTML, CSS, and JS
20 marzo, 2019 por
Using Bootstrap toolkit for Arduino based PLC's
Bernat Garcia

Introducción

Bootstrap es la biblioteca HTML, CSS y JS más popular para crear sitios web responsivos. Usando esta biblioteca podremos crear un sitio web muy atractivo que mostrará los datos de nuestros PLC basados en Arduino.  

Así que si usted está cansado de la apariencia típica y aburrida de sus sitios web hechos con http básico, eche un vistazo a este post que le mostrará una nueva manera de representar los paneles de su sitio web.   

Requisitos

Arquitectura de aplicaciones

El servidor web Bootstrap requiere que el cliente tenga acceso a Internet para visualizar la web. Este requisito se debe a que el PLC basado en Arduino, en este caso un M-Duino, pasará algún script al cliente y el clinet tiene que recoger de un servidor externo. Si el cliente no tiene acceso a Internet, el servidor web no se verá como se esperaba.  

La biblioteca de servidores HTTP de Arduino podrá crear el contenido HTTP en nuestro M-Duino.Este contenido es un archivo dinámico HTML que se coloca en nuestro controlador en la SRAM como una cadena. Por supuesto, este contenido tiene algunas limitaciones.  El contenido estará limitado para la SRAM.  


Software

 A continuación se muestra el código final para nuestro controlador industrial basado en Arudino:

/*
   Copyright (c) 2019 Boot&Work Corp., S.L. All rights reserved
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.
   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef DEBUG
#define DEBUG 0
#endif
#ifdef MDUINO_PLUS
#include <Ethernet2.h>
#else
#include <Ethernet.h>
#endif
#include <HttpServer.h>
byte mac[] = {0xAF, 0xBE, 0xCD, 0xDC, 0xEB, 0xFA};
IPAddress ip(10, 10, 11, 16);
HttpServer http;
uint32_t counter = 0;
////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
  Serial.begin(9600UL);
#if DEBUG
  while (!Serial);
#endif
  Ethernet.begin(mac, ip);
  attachInterrupt(digitalPinToInterrupt(I0_6), count, RISING);
#if DEBUG
  Serial.print("IP address: ");
  Serial.println(Ethernet.localIP());
#endif
  http.begin();
#if DEBUG
  Serial.println("HTTP server started");
#endif
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
  http.update();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void count() {
  ++counter;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void httpServerEvent(const HttpRequest &req, HttpResponse &res) {
#if DEBUG
  Serial.print("method: ");
  Serial.println(req.method);
  Serial.print("route: ");
  Serial.println(req.route);
  Serial.print("query string: ");
  Serial.println(req.queryString);
  Serial.print("body: ");
  Serial.println(req.body);
#endif
  if (req.route == "/") {
    serveRoot(req, res);
  } else if (req.route == "/status") {
    serveStatus(req, res);
  } else if (req.route == "/js") {
    serverScript(req, res);
  } else if (req.route == "/var/counter/reset") {
    counter = 0;
    res.text(String(counter));
  } else if (req.route == "/q0_0/HIGH") {
    digitalWrite(Q0_0, HIGH);
    res.text("ON");
  } else if (req.route == "/q0_0/LOW") {
    digitalWrite(Q0_0, LOW);
    res.text("OFF");
  } else if (req.route == "/q0_1/HIGH") {
    digitalWrite(Q0_1, HIGH);
    res.text("ON");
  } else if (req.route == "/q0_1/LOW") {
    digitalWrite(Q0_1, LOW);
    res.text("OFF");
  } else {
    // Send an error
    res.send("Not Found", "text/plain", 404, "Not Found");
  }
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void serveRoot(const HttpRequest &req, HttpResponse &res) {
    // Send HTML content
    String html = "<!doctype html>"
    "<html>"
    "<head>"
    "<meta charset='utf-8'>"
    "<meta name='viewport' content='width=device-width,initial-scale=1,shrink-to-fit=no'>"
    "<title>Web monitor by Industrial Shields</title>"
    "<link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css'>"
    "</head>"
    "<body>"
    "<div class='container'>"
    // TOOLBAR
    "<nav class='navbar navbar-expand-lg'>"
    "<a class='navbar-brand href='#'>Web monitor by Industrial Shields</a>"
    "</nav>"
    // VALUES TABLE
    "<div class='row'>"
    "<h3>Values</h3>"
    "</div>"
    "<div class='row'>"
    "<table class='table table-striped'>"
    "<thead>"
    "<tr>"
    "<th scope='col'>Name</th>"
    "<th scope='col' class='text-right'>Value</th>"
    "<th scope='col'>Actions</th>"
    "</tr>"
    "</thead>"
    "<tbody>"
    "<tr>"
    "<td>Millis</td>"
    "<td class='text-right' id='millis'></td>"
    "<td></td>"
    "</tr>"
    "<tr>"
    "<td>I0.5</td>"
    "<td class='text-right' id='i0_5'></td>"
    "<td></td>"
    "</tr>"
    "<tr>"
    "<td>I0.6 counter</td>"
    "<td class='text-right' id='counter'></td>"
    "<td><button type='button' class='btn btn-primary' onclick='resetCounter()'>Reset</td>"
    "</tr>"
    "</tbody>"
    "</table>"
    "</div>"
    // OUTPUTS ACTIONS
    "<div class='row'>"
    "<h3>Outputs</h3>"
    "</div>"
    "<div class='row'>"
    "<div class='col-4'>"
    "RED LED <span class='badge badge-primary' id='q0_0'></span>"
    "</div>"
    "<div class='col-4'>"
    "<button type='button' class='btn btn-danger' onclick='setQ0_0(\"HIGH\")'>ON</button>"
    "<button type='button' class='btn btn-secondary' onclick='setQ0_0(\"LOW\")'>OFF</button>"
    "</div>"
    "</div>"
    "<div class='row'>"
    "<div class='col-4'>"
    "GREEN LED <span class='badge badge-primary' id='q0_1'></span>"
    "</div>"
    "<div class='col-4'>"
    "<button type='button' class='btn btn-success' onclick='setQ0_1(\"HIGH\")'>ON</button>"
    "<button type='button' class='btn btn-secondary' onclick='setQ0_1(\"LOW\")'>OFF</button>"
    "</div>"
    "</div>"
    "</div>"
    "<script src='https://code.jquery.com/jquery-3.3.1.min.js'></script>"
    "<script src='https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js'></script>"
    "<script src='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js'></script>"
    "<script src='/js'></script>"
    "</body>"
    "</html>";
    res.html(html);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void serverScript(const HttpRequest &req, HttpResponse &res) {
  String content = "function update() {"
    "$.get('/status', function(d){"
    "var s = d.split(' ');"
    "document.getElementById('millis').innerText = s[0];"
    "document.getElementById('i0_5').innerText = s[1];"
    "document.getElementById('counter').innerText = s[2];"
    "document.getElementById('q0_0').innerText = s[3];"
    "document.getElementById('q0_1').innerText = s[4];"
    "});"
    "}"
    "function resetCounter() {$.post('/var/counter/reset', function(d) {document.getElementById('counter').innerText = d;});}"
    "function setQ0_0(v) {$.post('/q0_0/' + v, function(d) {document.getElementById('q0_0').innerText = d;});}"
    "function setQ0_1(v) {$.post('/q0_1/' + v, function(d) {document.getElementById('q0_1').innerText = d;});}"
    "setInterval(update, 1000);";
  res.send(content, "application/javascript");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void serveStatus(const HttpRequest &req, HttpResponse &res) {
  String content;
  content += String(millis());
  content += ' ';
  content += String(digitalRead(I0_5) ? "ON" : "OFF");
  content += ' ';
  content += String(counter);
  content += ' ';
  content += String(digitalRead(Q0_0) ? "ON" : "OFF");
  content += ' ';
  content += String(digitalRead(Q0_1) ? "ON" : "OFF");
  res.text(content);
}

 
 
Using Bootstrap toolkit for Arduino based PLC's
Bernat Garcia
20 marzo, 2019
Compartir
Archivar

¿Buscas tu controlador lógico programable ideal?

Echa un vistazo a esta comparativa de producto de varios controladores industriales basados en Arduino.

Comparamos entradas, salidas, comunicaciones y otras especificaciones con las de los equipos de otras marcas destacadas.


Comparación PLC industrial>>>

¿Quieres más información?

¡Rellena el formulario!

¡Cuéntame más!