×

ARDUINO

Control d’accés amb contrasenya. Orgue de llums. Comparativa de editors Arduino. Projecte bon Nadal. Sensor de gas i de fums. Control de la qualitat del aire interior (CO2) amb semàfor LED.

NodeMCU

NodeMCU-ThingSpeak. ThingSpeak. NodeMCU com AccessPoint. Control de la llum de casa per web. Control de un led per el mòbil. Sistema de fitxers en ESP8266. Altura del nivell d'aigua. Avis d’alarma a Telegram. Control de la llum de casa des de Telegram. Control de la intensitat de llum de un LED per Internet. Magatzematge de temperatura i humitat en Thinger. Publicar temperatura i humitat en Google Sheets. ESP8266 i Firebase. ESP8266-BME280 Firebase. La bàscula. ESP8266 NodeMCU amb cèl·lula de càrrega..

ESP32

ESP32-CAM, exemple de prova. Esp32-Cam captura fotos per ser vistes en la WEB. Pujar fotos a un servidor FTP amb ESP32-CAM. Foto amb ESP32-CAM i Telegram. Alarma amb avis a Telegram, utilitzant la placa ESP32-CAM.

PROGRAMACIÓ

Matemàtiques. App Inventor tutorial. MicroPython en ESP8266. Visual Estudio Code per Arduino

Intel·ligència artificial

Classificador d’imatges.

SERVIDORS

Instal·lar i configurar Apache en Ubuntu. Accés a un servidor Linux remotament. Client i Servidor FTP.

MÀQUINES VIRTUALS

Màquina virtual UBUNTU. WindowsXP en Virtualbox.

ELECTRÒNICA

Simulador Multisim. Simulador Proteus.

BASE DE DADES

MySQL. Instal·lació. MySQL. Aplicacions.

JAVA

Netbeans Maven MySQL. Java+Netbeans+Maven+EclipseLink+MySQL Aplicació d’escriptori JavaFX App JavaFX amb SceneBuilder App Java-Swing
favicon
logo

Tresavis

Benvinguts al blog de tresavis de noves tecnologies i més.

Correu : tresavis3@gmail.com

facebook   Instagram   youtube   x   tiktok

☰ Pràctiques   ☰ Articles

Esp32-Cam captura fotos per ser vistes en la WEB.

Descripció.

Enviant ordres a la placa ESP32-CAM, aquesta pren fotos. Amb el navegador podem veure la ultima foto capturada. Les fotos es guarden en el sistema de fitxers interns de la placa (SPIFFS).

Contingut:

esp1

ESP32-CAM.

El mòdul ESP32-CAM, porta incorporat el microcontrolador ESP32, la càmera OV2640, varis pins GPIOs per connectar perifèrics i un slot per targeta microSD.

ESP32-CAM no porta un connector USB. Necessitem un programador FTDI per pujar codi al microcontrolador a traves dels pins sèrie UOT i UOR.

esp32-cam

Per mes informació consultar:

esp32-cam.php

Components.

ESP32-CAM amb càmera OV2640.
Programador FTDI.
IDE de Arduino.
Cable USB-miniUSB.
        componets

Pagina WEB.

La pagina web te que mostrar tres botons: Captura foto, refresca pagina i rotar imatge. També un espai per mostrar la foto.

La ultima foto es guarda en el sistema de fitxers interns SPIIFS. Si reiniciem la placa, la ultima foto capturada sempre la tenim accessible.

URLs que accepta el servidor:

A la petició “192.168.1.123/”, el servidor envia el index.

A la petició “192.168.1.123/captura”, el servidor canvia la variable “novaCaptura” a true.

A la petició “192.168.1.123/foto-guardada”, el servidor envia la foto.

Al clicar en el botó CAPTURAR FOTO, el navegador envia al servidor el get “/captura”.

Per mostrar la foto en el navegador, es fa servir el get “foto-guardada”.

  <div><img src="foto-guardada" id="foto" width="50%"/></div>
mobil

Instal·lar ESP32 add-on en el IDE de Arduino.

Per programar el ESP32 fen servir el IDE de Arduino, aquest es te que configurar amb el ESP32 add-on.

Consultar en:

https://esp32-cam.php#instalar

Connexió de ESP32-CAM amb el programador FTDI.

Per connectar el IDE amb la placa per programar-la, es necessita el programador FTDI

Consultar en:

https://esp32-cam.php#conexio

Llibreries.

Per construir el servidor WEB necessitem la llibreria ESPAsyncWebServer . També es requereix la llibreria Async TCP.

Passos a seguir per instal·lar la llibreria ESPAsyncWebServer.

1. Pagina de descarrega :

https://github.com/me-no-dev/ESPAsyncWebServer

2. Des comprimir el .zip i obtenim una carpeta nomenada: ESPAsyncWebServer-master.

3. Re nombrar la carpeta a ESPAsyncWebServer, treure el mot “-master”.

4. Moure la carpeta ESPAsyncWebServer a la nostre carpeta libraries de la carpeta de Arduino.

Com alternativa podem instal·lar la llibreria de la següent manera: En el IDE de Ardino anar a Esbós/Inclou biblioteca/Afegeix una biblioteca .ZIP... i seleccionar la carpeta descarregada.

Passos a seguir per instal·lar la llibreria Async TCP.

1. Pagina de descarrega :

https://github.com/me-no-dev/AsyncTCP/archive/master.zip

2. Des comprimir el .zip i obtenim una carpeta nomenada: AsyncTCP-master.

3. Re nombrar la carpeta a AsyncTCP, treure el mot “-master”.

4. Moure la carpeta AsyncTCP a la nostre carpeta libràries de la carpeta de Arduino.

Com alternativa podem instal·lar la llibreria de la següent manera: En el IDE de Arduino anar a Esbós/Inclou biblioteca/Afegeix una biblioteca .ZIP... i seleccionar la carpeta descarregada.

SPIFFS.

Guardem la imatge en el sistema intern de fitxers del ESP32, SPIFFS (Serial Peripheral Interface Flsh File System). SPIFFS es un sistema de fitxers lleuger en el chip de la memòria flash que incorpora el ESP32.

Consultar en:

https://spiffs.php

Codi.

esp32-foto-webV2.ino

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-cam-take-photo-display-web-server/
  Codi modificat per tresavis https://tresavis.cat
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
   IMPORTANT!!! 
   - Placa "AI Thinker ESP32-CAM"
   - GPIO 0 connectat a GND per programar ESP32
   - Despres de connectar GPIO 0 a GND, prem el RESET de ESP32-CAM per posar la placa en flashing mode
*********/
// llibreries
#include "WiFi.h"
#include "esp_camera.h"
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "soc/soc.h"           // Disable brownout problems
#include "soc/rtc_cntl_reg.h"  // Disable brownout problems
#include "driver/rtc_io.h"
#include <ESPAsyncWebServer.h>
#include <StringArray.h>
#include <SPIFFS.h>
#include <FS.h>


// WiFi
const char* ssid = "mirablau";
const char* password = "**********";

// Creem un objecte de la classe AsyncWebServer en el port 80
AsyncWebServer server(80);

boolean novaCaptura = false;

// Nom i ruta de la foto per ser guardada en SPIFFS
#define RUTA_FOTO "/foto.jpg"

// Pins de la camara OV2640  (CAMERA_MODEL_AI_THINKER)
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

//Pagina WEB
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    body { text-align:center; }
    .vertical { margin-bottom: 10%; }
    .horizontal{ margin-bottom: 0%; }
  </style>
</head>
<body>
  <div id="contanidor">
    <h1>TresAvis</h1>
    <h2>ESP32-CAM. Ultima foto</h2>
    <p>Esperar mes de 5 segons per capturar i guardar la foto.</p>
    <p>
      <button onclick="rotarFoto();">ROTAR FOTO</button>
      <button onclick="capturarFoto();">CAPTURAR FOTO</button>
      <button onclick="location.reload();">REFRESCAR PAGINA</button>
    </p><hr><hr>
  </div>
  <div><img src="foto-guardada" id="foto" width="50%"/></div>
</body>
<script>
 
  // Envia la URL /captura al servidor i ESP32-CAM dispara la camara.
  function capturarFoto() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', "/captura", true);
    xhr.send();
  }
  // Suma 90 graus i compara si graus/90 es impar o par
  // 90/90=1, 180/90=2, ....
  // Si es impar agafa la classe vertical que canvia el margin-botton, perque la imatge no se sobre-posi als botons
  // La imatge rota cada vegada 90º en sentit del rellotge.
  var graus = 0;
  function rotarFoto() {
    var imatge = document.getElementById("foto");
    graus += 90; 
     if(esImpar(graus/90)){ 
      document.getElementById("contanidor").className = "vertical"; 
      }
    else{ 
      document.getElementById("contanidor").className = "horizontal"; 
      }
    imatge.style.transform = "rotate(" + graus + "deg)";
  } 
 function esImpar(n) { 
    return Math.abs(n % 2) == 1; 
  }
</script>
</html>)rawliteral";

//////////////////// setpup() ///////////////////////////////////////////
void setup() {
  // Serial port 115200
  Serial.begin(115200);

  // Connectar a la Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connectant a la WiFi...");
  }
  // Montar el sistema de fitxers SPIFFS 
  if (!SPIFFS.begin(true)) {
    Serial.println("Error al montar SPIFFS");
    ESP.restart();
  }
  else {
    delay(500);
    Serial.println("SPIFFS montat satisfactoriament");
  }

  //  ESP32 imprimeix la IP local 
  Serial.print("IP Adressa: http://");
  Serial.println(WiFi.localIP());

  // Turn-off the 'brownout detector' detector de apagades
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

  // Configurar la camara OV2640
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;

  if (psramFound()) {
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }
  // Iniciar la Camara
  esp_err_t error = esp_camera_init(&config);
  if (error != ESP_OK) {
    Serial.printf("Camara la fallat amb error 0x%x", error);
    ESP.restart();
  }
  // URLs que accepta el servidor:
  // 192.168.1.123/
  // 192.168.1.123/captura
  // 192.168.1.123/foto-guardada
  // A la petició "/"  el servidor envia el index
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/html", index_html);
  });
  // A la petició "/captura" el servidor posa la variable novaCaptura a true i envia un missatge
  server.on("/captura", HTTP_GET, [](AsyncWebServerRequest * request) {
    novaCaptura = true;
    request->send_P(200, "text/plain", "Capturant foto");
  });
  // A la petició "/foto-guardada" el servidor envia la foto
  server.on("/foto-guardada", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, RUTA_FOTO, "image/jpg", false);
  });

  // Inicia el servidor
  server.begin();
  
  //Llista de les fotos guardades en SPIFFS
  File root = SPIFFS.open("/");
  File file = root.openNextFile();
  while(file){
      Serial.print("FILE: ");
      Serial.println(file.name());
      file = root.openNextFile();
  }
}

///////////////////////// loop() //////////////////////////////////
void loop() {
  if (novaCaptura) {
    capturarFotoGuardarSpiffs();
    novaCaptura = false;
  }
  delay(1);
}

// Comproba si la captura ha sigut exitosa
// retorna true si el tamnay de la foto es mes gran de 100 bytes
bool checkFoto( fs::FS &fs ) {
  File f_foto = fs.open( RUTA_FOTO );
  unsigned int foto_tamany = f_foto.size();
  return ( foto_tamany > 100 );
}

// Captura una foto i la guarda en SPIFFS
void capturarFotoGuardarSpiffs( void ) {
  camera_fb_t * fb = NULL; // pointer
  bool ok = 0; // Boolean que indica si la foto ha estat presa correctament
  // Bucle do while que es repetirà mentres la variable ok sigui falsa
  do {
    // Captura la foto
    Serial.println("Capturant foto...");
    // ESP32-CAM fa la foto
    fb = esp_camera_fb_get();
    if (!fb) {
      Serial.println("La captura ha fallat");
      return;
    }

    // Guarda la foto en el sistema de fitxers SPIFFS
    Serial.printf("El nom de la foto es: %s\n", RUTA_FOTO);
    File fitxer = SPIFFS.open(RUTA_FOTO, FILE_WRITE);

    // Inserta les dades de la foto en el fitxer
    if (!fitxer) {
      Serial.println("Ha fallat obrir el fitxer en mode escritura");
    }
    else {
      fitxer.write(fb->buf, fb->len); // payload (image), payload length
      Serial.print("La foto ha estat guardada en: ");
      Serial.print(fitxer.name());
      Serial.print(" - Tamany: ");
      Serial.print(fitxer.size());
      Serial.println(" bytes");
    }
    // Tancar el fitxer
    fitxer.close();
    esp_camera_fb_return(fb);

    // Comproba si el fitxer que gurda la foto no esta buit.
    ok = checkFoto(SPIFFS);
  } while ( !ok );
}

Explicacions del codi.

Primer de tot el codi te de incloure les llibreries necessàries per la càmera, el servidor web i el sistema de fitxers SPIFFS:

// Llibreries:
#include "WiFi.h"
#include "esp_camera.h"
#include "esp_timer.h"
#include "img_converters.h"
#include "Arduino.h"
#include "soc/soc.h"           // Desactiva apagades per falta de potencia
#include "soc/rtc_cntl_reg.h"  // Desactiva apagades per falta de potencia
#include "driver/rtc_io.h"
#include <ESPAsyncWebServer.h>
#include <StringArray.h>
#include <SPIFFS.h>
#include <FS.h>

Les dades de la WiFi, perquè el ESP32-CAM pugui connectar a la xarxa local:

// WiFi
const char* ssid = "mirablau";
const char* password = "*********";

Creem un objecte AsyncWebServer en el port 80, pot ser un altre port, però al connectar amb el navegador al servidor, el tenim que especificar:

// Creem un objecte de la classe AsyncWebServer en el port 80
AsyncWebServer server(80);

Quan la variable novaCaptura es true es dispara la nova foto:

boolean novaCaptura = false;

La constant RUTA_FOTO defineix el lloc i el nom on es guarda la ultima foto:

// Nom i ruta de la foto per ser guardada en SPIFFS
#define RUTA_FOTO "/foto.jpg"

Pagina web:

La web conté tres botons, CAPTURAR FOTO, ROTAR FOTO I REFRESCAR PAGINA:

      <button onclick="rotarFoto();">ROTAR FOTO</button>
      <button onclick="capturarFoto();">CAPTURAR FOTO</button>
      <button onclick="location.reload();">REFRESCAR PAGINA</button>

Al clicar sobre els botons s’executen les funcions capturarFoto(), rotarFoto() i reload():

  // Envia la URL /captura al servidor i ESP32-CAM dispara la camara.
  function capturarFoto() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', "/captura", true);
    xhr.send();
  }
  // Suma 90 graus i compara si graus/90 es impar o par
  // 90/90=1, 180/90=2, ....
  // Si es impar agafa la classe vertical que canvia el margin-botton, perque la imatge no se sobre-posi als botons
  // La imatge rota cada vegada 90º en sentit del rellotge.
  var graus = 0;
  function rotarFoto() {
    var imatge = document.getElementById("foto");
    graus += 90; 
     if(esImpar(graus/90)){ 
      document.getElementById("contanidor").className = "vertical"; 
      }
    else{ 
      document.getElementById("contanidor").className = "horizontal"; 
      }
    imatge.style.transform = "rotate(" + graus + "deg)";
  } 
 function esImpar(n) { 
    return Math.abs(n % 2) == 1; 
  }

SPIFFS:

  // Montar el sistema de fitxers SPIFFS 
  if (!SPIFFS.begin(true)) {
    Serial.println("Error al montar SPIFFS");
    ESP.restart();
  }
  else {
    delay(500);
    Serial.println("SPIFFS montat satisfactoriament");
  }

ESP32 desposa de un sistema de interrupciones que es dispara per diferents motius. Per exemple quan la bateria es baixa, la placa s’apaga:

  // Des-activa the 'brownout detector' detector de apagades per falta de potencia
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

Configurar i iniciar la cámara:

La configuració dels pins i paràmetres de la càmera es igual sempre, es copiar i enganxar:

  // Iniciar la Camara
  esp_err_t error = esp_camera_init(&config);
  if (error != ESP_OK) {
    Serial.printf("Camara la fallat amb error 0x%x", error);
    ESP.restart();
  }

Peticions que enviem al servidor:

  // URLs que accepta el servidor:
  // 192.168.1.123/
  // 192.168.1.123/captura
  // 192.168.1.123/foto-guardada
  // A la petició "/"  el servidor envia el index
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/html", index_html);
  });
  // A la petició "/captura" el servidor posa la variable novaCaptura a true i envia un missatge
  server.on("/captura", HTTP_GET, [](AsyncWebServerRequest * request) {
    novaCaptura = true;
    request->send_P(200, "text/plain", "Capturant foto");
  });
  // A la petició "/foto-guardada" el servidor envia la foto
  server.on("/foto-guardada", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, RUTA_FOTO, "image/jpg", false);
  });

  // Inicia el servidor
  server.begin();
  

loop(), si novaCaptura es true s’executa la funció capturarFotoGuardarSpiffs() i torna a posar la variable novaCaptura a false:

void loop() {
  if (novaCaptura) {
    capturarFotoGuardarSpiffs();
    novaCaptura = false;
  }
  delay(1);
}

La funció “capturarFotoGuardarSpiffs()”:

En un bucle do-While que s’executa sempre que la variable ok sigui false, dispara la foto i la guarda en el sistema de fitxers SPIFFS. Comprova si la captura ha sigut exitosa, si es ok s’acaba el bucle.

// Captura una foto i la guarda en SPIFFS
void capturarFotoGuardarSpiffs( void ) {
  // Punter al buffer *fb
  camera_fb_t * fb = NULL; // pointer
  bool ok = 0; // Boolean que indica si la foto ha estat presa correctament
  // Bucle do while que es repetirà mentres la variable ok sigui falsa
  do {
    // Captura la foto
    Serial.println("Capturant foto...");
    // ESP32-CAM fa la foto
    // Escriu el buffer
    fb = esp_camera_fb_get();
    if (!fb) {
      Serial.println("La captura ha fallat");
      return;
    }

    // Guarda la foto en el sistema de fitxers SPIFFS
    Serial.printf("El nom de la foto es: %s\n", RUTA_FOTO);
    File fitxer = SPIFFS.open(RUTA_FOTO, FILE_WRITE);

    // Inserta les dades de la foto en el fitxer
    if (!fitxer) {
      Serial.println("Ha fallat obrir el fitxer en mode escritura");
    }
    else {
      fitxer.write(fb->buf, fb->len); // payload (image), payload length
      Serial.print("La foto ha estat guardada en: ");
      Serial.print(fitxer.name());
      Serial.print(" - Tamany: ");
      Serial.print(fitxer.size());
      Serial.println(" bytes");
    }
    // Tancar el fitxer
    fitxer.close();
    // Buida el buffer
    esp_camera_fb_return(fb);

    // Comproba si el fitxer que gurda la foto no esta buit.
    ok = checkFoto(SPIFFS);
  } while ( !ok );

La funció checkFoto retorna true si la captura ha sigut exitosa, altrament retorna false. Comprova la grandària del fitxer, si es mes gran de 100 Bytes:

// Comproba si la captura ha sigut exitosa
// retorna true si el tamnay de la foto es mes gran de 100 bytes
bool checkFoto( fs::FS &fs ) {
  File f_foto = fs.open( RUTA_FOTO );
  unsigned int foto_tamany = f_foto.size();
  return ( foto_tamany > 100 );
}

Prova de la instal·lació.

Recordar que es té que desfer el pont entre GND i GPOI0 fet servir per pujar el codi a la placa.

Fer un reset a la placa.

El monitor sèrie mostra la IP que te el servidor WEB. En el nostre cas es:

192.168.1.123

monitor

El resultat es el següent:

esp2
esp3

Altres projectes relacionats.

Afegir un sensor detector de moviment i fer la foto al detectar canvis.
Enviar les fotos a un servidor FTP.
Afegir la possibilitat de fer vídeo Streaming.
Fer servir un BOT de Telegram per veure les imatges.
    
         

Contingut.


Nosaltres

casa1
casa2
Balleu-me amb la vostra bellesa amb un violí ardent
Dance me to your beauty with a burning violin

Balleu-me pel pànic fins que estigueu reunits amb seguretat
Dance me through the panic till I'm gathered safely in

Aixeca’m com una branca d’olivera i fes-me el meu colom cap a casa
Lift me like an olive branch and be my homeward dove

Balla amb mi fins al final de l'amor
Dance me to the end of love

Balla amb mi fins al final de l'amor
Dance me to the end of love
Ah, deixeu-me veure la vostra bellesa quan els testimonis se n’hagin anat
Oh, let me see your beauty when the witnesses are gone

Deixa’m sentir-te en moviment com ho fan a Babilònia
Let me feel you moving like they do in Babylon

Mostra’m a poc a poc el que només sé dels límits
Show me slowly what I only know the limits of

Balla amb mi fins al final de l'amor
Dance me to the end of love

Balla amb mi fins al final de l'amor
Dance me to the end of love
Ballar-me fins al casament ara, ballar-me sense parar
Dance me to the wedding now, dance me on and on

Balla’m molt tendrament i balla’m molt llarg
Dance me very tenderly and dance me very long

Tots dos estem per sota del nostre amor, estem tots dos per sobre
We're both of us beneath our love, we're both of us above

Balla amb mi fins al final de l'amor
Dance me to the end of love

Balla amb mi fins al final de l'amor
Dance me to the end of love
Balleu-me amb els nens que demanen que neixin
Dance me to the children who are asking to be born

Balleu-me a través de les cortines que han perdut els nostres petons
Dance me through the curtains that our kisses have outworn

Aixequeu ara una tenda de refugi, tot i que cada fil està esquinçat
Raise a tent of shelter now, though every thread is torn

Balla amb mi fins al final de l'amor
Dance me to the end of love
Balleu-me amb la vostra bellesa amb un violí ardent
Dance me to your beauty with a burning violin

Balleu-me pel pànic fins que estigueu reunits amb seguretat
Dance me through the panic till I'm gathered safely in

Toca’m amb la mà nua o toca’m amb el guant
Touch me with your naked hand or touch me with your glove

Balla amb mi fins al final de l'amor
Dance me to the end of love

Balla amb mi fins al final de l'amor
Dance me to the end of love

Balla amb mi fins al final de l'amor
Dance me to the end of love
Font: LyricFind
Compositors: Leonard Cohen
Lletra de Dance Me to the End of Love © Sony/ATV Music Publishing LLC    

caminata https://strava.app.link/nDpMEjvqegb
retol
cami
bassa1
bassa2

Tags

Noves tecnologies WEB Arduino Domótica MycroPython NodeMCU IoT Java ESP8266 Lora C++ Programació Server-Client