TaulellDigital

Hoy vengo a hablar de un proyecto que hice en la hackovid, una hackatón para combatir los problemas derivados del COVID-19.

Mi proyecto se llama TaulellDigital:

https://www.taulelldigital.cat

Consiste en una aplicación web que conecta a clientes con productores de proximidad. Sólo hace falta buscar en el mapa productores y ponerse en contacto con ellos. Si eres productor de proximidad, TaulellDigital te permite promocionarte y automatizar muchos aspectos relacionados con el marketing tradicional.

Aquí tenéis un vídeo explicativo:

Y el enlace a Github:
https://github.com/cefaloide/taulellDigital

Un saludo!

Arduino Serial MP3 Player YX5300 chip

En esta entrada explicaré como reproducir MP3 con arduino y la placa YX5300 de Catalex:

Este módulo utiliza una tarjeta SD para almacenar las canciones en formato MP3 o WAV. La tarjeta debe estar formateada a FAT32 o FAT16.

Se recomienda guardar los audios en carpetas numeradas, aunque solo se tenga una carpeta, la manera más cómoda (por ejemplo si se quiere reproducir todas las canciones de una carpeta en loop) es seguir la siguiente estructura:

.
├── 01
│   ├── 001-blue-piano.mp3
│   └── 002-gettin-ready.mp3
├── 02
│   ├── 001-ukulele-in-my-heart.mp3
│   ├── 002-inspiring-innovation.mp3
│   └── 003-thanks-for-the-memories.mp3
└── 03
    ├── 001-a-hero-is-born.mp3
    └── 002-lullaby.mp3

Para la conexión del cableado si utilizamos Arduino Uno o Nano será la siguiente:
Serial MP3 Player -> ARDUINO
VCC -> 5V o 3.3V
GND -> GND
TX-> D5
RX -> D6

Si utilizamos Arduino Mega se debe utilizar la siguiente conexión que utiliza el Serial3 (en el código también se tendrán que comentar/descomentar un par de líneas):
Serial MP3 Player -> ARDUINO
VCC -> 5V o 3.3V
GND -> GND
TX-> 15 RX3
RX -> 14 TX3

También deberemos conectar a la salida del Jack 3.5 unos altavoces/auriculares.

Después ya podemos cargar el siguiente código o descargarlo de Github:

/***********************************************************/
// Demo for the Serial MP3 Player Catalex (YX5300 chip)
// Hardware: Serial MP3 Player *1
// Board:  Arduino UNO
// http://www.dx.com/p/uart-control-serial-mp3-music-player-module-for-arduino-avr-arm-pic-blue-silver-342439#.VfHyobPh5z0
//
//
//


// Uncomment SoftwareSerial for Arduino Uno or Nano.

#include <SoftwareSerial.h>

#define ARDUINO_RX 5  //should connect to TX of the Serial MP3 Player module
#define ARDUINO_TX 6  //connect to RX of the module

SoftwareSerial mp3(ARDUINO_RX, ARDUINO_TX);
//#define mp3 Serial3    // Connect the MP3 Serial Player to the Arduino MEGA Serial3 (14 TX3 -> RX, 15 RX3 -> TX)

static int8_t Send_buf[8] = {0}; // Buffer for Send commands.  // BETTER LOCALLY
static uint8_t ansbuf[10] = {0}; // Buffer for the answers.    // BETTER LOCALLY

String mp3Answer;           // Answer from the MP3.

boolean autoResume = true;

/************ Command byte **************************/
#define CMD_NEXT_SONG     0X01  // Play next song.
#define CMD_PREV_SONG     0X02  // Play previous song.
#define CMD_PLAY_W_INDEX  0X03
#define CMD_VOLUME_UP     0X04
#define CMD_VOLUME_DOWN   0X05
#define CMD_SET_VOLUME    0X06

#define CMD_SNG_CYCL_PLAY 0X08  // Single Cycle Play.
#define CMD_SEL_DEV       0X09
#define CMD_SLEEP_MODE    0X0A
#define CMD_WAKE_UP       0X0B
#define CMD_RESET         0X0C
#define CMD_PLAY          0X0D
#define CMD_PAUSE         0X0E
#define CMD_PLAY_FOLDER_FILE 0X0F

#define CMD_STOP_PLAY     0X16
#define CMD_FOLDER_CYCLE  0X17
#define CMD_SHUFFLE_PLAY  0x18 //
#define CMD_SET_SNGL_CYCL 0X19 // Set single cycle.

#define CMD_SET_DAC 0X1A
#define DAC_ON  0X00
#define DAC_OFF 0X01

#define CMD_PLAY_W_VOL    0X22
#define CMD_PLAYING_N     0x4C
#define CMD_QUERY_STATUS      0x42
#define CMD_QUERY_VOLUME      0x43
#define CMD_QUERY_FLDR_TRACKS 0x4e
#define CMD_QUERY_TOT_TRACKS  0x48
#define CMD_QUERY_FLDR_COUNT  0x4f

/************ Opitons **************************/
#define DEV_TF            0X02


/*********************************************************************/

void setup()
{
  Serial.begin(9600);
  mp3.begin(9600);
  delay(500);

  sendCommand(CMD_SEL_DEV, DEV_TF);
  delay(500);
}


void loop()
{
  char c = ' ';

  // If there a char on Serial call sendMP3Command to sendCommand
  if ( Serial.available() )
  {
    c = Serial.read();
    sendMP3Command(c);
  }

  // Check for the answer.
  if (mp3.available())
  {
    Serial.println(decodeMP3Answer());
  }
  delay(100);
}


/********************************************************************************/
/*Function sendMP3Command: seek for a 'c' command and send it to MP3  */
/*Parameter: c. Code for the MP3 Command, 'h' for help.                                                                                                         */
/*Return:  void                                                                */

void sendMP3Command(char c) {
  switch (c) {
    case '?':
    case 'h':
      Serial.println("HELP  ");
      Serial.println(" p = Play");
      Serial.println(" P = Pause");
      Serial.println(" > = Next");
      Serial.println(" < = Previous");
      Serial.println(" + = Volume UP");
      Serial.println(" - = Volume DOWN");
      Serial.println(" c = Query current file");
      Serial.println(" q = Query status");
      Serial.println(" v = Query volume");
      Serial.println(" x = Query folder count");
      Serial.println(" t = Query total file count");
      Serial.println(" 1 = Play folder 1");
      Serial.println(" 2 = Play folder 2");
      Serial.println(" 3 = Play folder 3");
      Serial.println(" 4 = Play folder 4");
      Serial.println(" 5 = Play folder 5");
      Serial.println(" S = Sleep");
      Serial.println(" W = Wake up");
      Serial.println(" r = Reset");
      break;


    case 'p':
      Serial.println("Play ");
      sendCommand(CMD_PLAY, 0);
      break;

    case 'P':
      Serial.println("Pause");
      sendCommand(CMD_PAUSE, 0);
      break;


    case '>':
      Serial.println("Next");
      sendCommand(CMD_NEXT_SONG, 0);
      sendCommand(CMD_PLAYING_N, 0x0000); // ask for the number of file is playing
      break;


    case '<':
      Serial.println("Previous");
      sendCommand(CMD_PREV_SONG, 0);
      sendCommand(CMD_PLAYING_N, 0x0000); // ask for the number of file is playing
      break;

    case '+':
      Serial.println("Volume Up");
      sendCommand(CMD_VOLUME_UP, 0);
      break;

    case '-':
      Serial.println("Volume Down");
      sendCommand(CMD_VOLUME_DOWN, 0);
      break;

    case 'c':
      Serial.println("Query current file");
      sendCommand(CMD_PLAYING_N, 0);
      break;
      
    case 'q':
      Serial.println("Query status");
      sendCommand(CMD_QUERY_STATUS, 0);
      break;

    case 'v':
      Serial.println("Query volume");
      sendCommand(CMD_QUERY_VOLUME, 0);
      break;

    case 'x':
      Serial.println("Query folder count");
      sendCommand(CMD_QUERY_FLDR_COUNT, 0);
      break;

    case 't':
      Serial.println("Query total file count");
      sendCommand(CMD_QUERY_TOT_TRACKS, 0);
      break;

    case '1':
      Serial.println("Play folder 1");
      sendCommand(CMD_FOLDER_CYCLE, 0x0101);
      break;

    case '2':
      Serial.println("Play folder 2");
      sendCommand(CMD_FOLDER_CYCLE, 0x0201);
      break;

    case '3':
      Serial.println("Play folder 3");
      sendCommand(CMD_FOLDER_CYCLE, 0x0301);
      break;

    case '4':
      Serial.println("Play folder 4");
      sendCommand(CMD_FOLDER_CYCLE, 0x0401);
      break;

    case '5':
      Serial.println("Play folder 5");
      sendCommand(CMD_FOLDER_CYCLE, 0x0501);
      break;

    case 'S':
      Serial.println("Sleep");
      sendCommand(CMD_SLEEP_MODE, 0x00);
      break;

    case 'W':
      Serial.println("Wake up");
      sendCommand(CMD_WAKE_UP, 0x00);
      break;

    case 'r':
      Serial.println("Reset");
      sendCommand(CMD_RESET, 0x00);
      break;
  }
}



/********************************************************************************/
/*Function decodeMP3Answer: Decode MP3 answer.                                  */
/*Parameter:-void                                                               */
/*Return: The                                                  */

String decodeMP3Answer() {
  String decodedMP3Answer = "";

  decodedMP3Answer += sanswer();

  switch (ansbuf[3]) {
    case 0x3A:
      decodedMP3Answer += " -> Memory card inserted.";
      break;

    case 0x3D:
      decodedMP3Answer += " -> Completed play num " + String(ansbuf[6], DEC);
      break;

    case 0x40:
      decodedMP3Answer += " -> Error";
      break;

    case 0x41:
      decodedMP3Answer += " -> Data recived correctly. ";
      break;

    case 0x42:
      decodedMP3Answer += " -> Status playing: " + String(ansbuf[6], DEC);
      break;

    case 0x48:
      decodedMP3Answer += " -> File count: " + String(ansbuf[6], DEC);
      break;

    case 0x4C:
      decodedMP3Answer += " -> Playing: " + String(ansbuf[6], DEC);
      break;

    case 0x4E:
      decodedMP3Answer += " -> Folder file count: " + String(ansbuf[6], DEC);
      break;

    case 0x4F:
      decodedMP3Answer += " -> Folder count: " + String(ansbuf[6], DEC);
      break;
  }

  return decodedMP3Answer;
}






/********************************************************************************/
/*Function: Send command to the MP3                                         */
/*Parameter:-int8_t command                                                     */
/*Parameter:-int16_ dat  parameter for the command                              */

void sendCommand(int8_t command, int16_t dat)
{
  delay(20);
  Send_buf[0] = 0x7e;   //
  Send_buf[1] = 0xff;   //
  Send_buf[2] = 0x06;   // Len
  Send_buf[3] = command;//
  Send_buf[4] = 0x01;   // 0x00 NO, 0x01 feedback
  Send_buf[5] = (int8_t)(dat >> 8);  //datah
  Send_buf[6] = (int8_t)(dat);       //datal
  Send_buf[7] = 0xef;   //
  Serial.print("Sending: ");
  for (uint8_t i = 0; i < 8; i++)
  {
    mp3.write(Send_buf[i]) ;
    Serial.print(sbyte2hex(Send_buf[i]));
  }
  Serial.println();
}



/********************************************************************************/
/*Function: sbyte2hex. Returns a byte data in HEX format.                 */
/*Parameter:- uint8_t b. Byte to convert to HEX.                                */
/*Return: String                                                                */


String sbyte2hex(uint8_t b)
{
  String shex;

  shex = "0X";

  if (b < 16) shex += "0";
  shex += String(b, HEX);
  shex += " ";
  return shex;
}




/********************************************************************************/
/*Function: sanswer. Returns a String answer from mp3 UART module.          */
/*Parameter:- uint8_t b. void.                                                  */
/*Return: String. If the answer is well formated answer.                        */

String sanswer(void)
{
  uint8_t i = 0;
  String mp3answer = "";

  // Get only 10 Bytes
  while (mp3.available() && (i < 10))
  {
    uint8_t b = mp3.read();
    ansbuf[i] = b;
    i++;

    mp3answer += sbyte2hex(b);
  }

  // if the answer format is correct.
  if ((ansbuf[0] == 0x7E) && (ansbuf[9] == 0xEF))
  {
    return mp3answer;
  }

  return "???: " + mp3answer;
}

Si estamos trabajando con Arduino Mega se deberá comentar la línea 13

#include <SoftwareSerial.h>

Comentar la línea 18 y descomentar la 19

SoftwareSerial mp3(ARDUINO_RX, ARDUINO_TX);
//#define mp3 Serial3    // Connect the MP3 Serial Player to the Arduino MEGA Serial3 (14 TX3 -> RX, 15 RX3 -> TX)

Ahora podremos manipular el reproductor a través del monitor serie del propio IDE de Arduino. Una vez subido el código al Arduino abrimos el monitor serie:

Si todo está correcto nos mostrará el texto:

Si introducimos la letra «h» nos mostrará el menu de ayuda con las diferentes opciones disponibles:

Si introducimos la letra «p» se ejecutará un audio y si introducimos «1» ejecutará todas las canciones de la carpeta 01.

Para más información sobre el funcionamiento del módulo puedes dirigirte a mi repositorio de Github donde se encuentra más documentación:
https://github.com/cefaloide/ArduinoSerialMP3Player

Referencias:
https://andrologiciels.wordpress.com/arduino/son-et-arduino/mp3/catalex-mp3-serie/

http://www.jarzebski.pl/arduino/komponenty/modul-mp3-z-ukladem-yx5300.html

https://www.carnetdumaker.net/articles/utiliser-un-lecteur-serie-de-fichiers-mp3-avec-une-carte-arduino-genuino/

Archivo ejecutable .bat para abrir chrome en modo kiosk e incognito

Para hacer un archivo ejecutable que abra el navegador Chrome en modo kiosk se debe crear un archivo de texto y guardar en formato .bat con el siguiente contenido:

start chrome.exe --kiosk http://joanruedapauweb.com

Si se quiere abrir una web que se encuentra en el propio ordenador, se puede navegar por las carpetas de la siguiente manera:

::	Ejemplo estructura
::	archivo.bat
::		|->	nombre_carpeta
::				|-> index.html

start chrome.exe --incognito --kiosk %cd%\nombre_carpeta\index.html

En el ejemplo anterior también se abre en modo incógnito.

Servidor Web LAMP Raspberry Pi

Hoy explicaré como hacerte un servidor LAMP (Linux Apache MySQL PHP) con tu Raspberry Pi.

En primer lugar debes asegurarte de tener configurada la IP fija, aquí se explica como.

En segundo lugar debes actualizar el apt-get para preparar las instalaciones, así que en línea de comando escribes las sentencias correspondientes:

sudo apt-get update
sudo apt-get upgrade

Y ya pasamos por fin a las intalaciones 🙂

Instalamos Apache:

sudo apt-get install apache2

Instalamos PHP y varios paquetes:

sudo apt-get install php5
sudo apt-get install libapache2-mod-php5 libapache2-mod-perl2 php5 php5-cli php5-common php5-curl php5-dev php5-gd php5-imap php5-ldap php5-mhash php5-mysql php5-odbc

Podemos crear un archivo phpinfo para ver la información:

sudo nano /var/www/html/info.php

Dentro del archivo escribimos:

<?php
      phpinfo();
?>

Ahora podemos comprobar entrando en el navegador web desde la Raspberry la url: http://localhost/info.php

O si nos conectamos de manera remota (en el ejemplo la ip es 192.168.1.100), introducimos la siguiente url en nuestro navegador web: http://192.168.1.100/info.php

Podremos ver algo parecido a esto:
capturaphpinfo

Instalamos MySQL:

sudo apt-get install mysql-server

Ahora podemos instalar phpMyAdmin para gestionar via web la Base de Datos, para ello primero haremos:

sudo apt-get install libapache2-mod-auth-mysql php5-mysql phpmyadmin

Mientras se instala nos pedirá el tipo de servidor instalado, seleccionamos «apache2».
También nos preguntará la contraseña que tiene la base de datos y nos pedirá una contraseña para el phpMyAdmin.

Ahora queda configurar Apache para trabajar con phpMyAdmin:

sudo nano /etc/apache2/apache2.conf

Y añadimos al final del documento (recuerda que puedes avanzar más rápido con Ctrl+V) la siguiente línea:

Include /etc/phpmyadmin/apache.conf

Guardamos el documento y reiniciamos apache:

sudo /etc/init.d/apache2 restart

Ahora si introducimos en el navegador web de la Rapberry:
http://localhost/phpmyadmin

O si lo hacemos desde remoto (en el ejemplo la ip es 192.168.1.100), introducimos en nuestro navegador web: http://192.168.1.100/phpmyadmin

Nos aparecerá la pantalla de login de phpmyadmin:

capturaphpmyadmin

Ahora ya podemos gestionar por la web la base de datos, bieeen!

Fuentes:
https://geekytheory.com/tutorial-raspberry-pi-crear-servidor-web/

http://www.geothread.net/building-a-lamp-server-on-the-raspberry-pi-computer/

http://raspipress.com/2012/09/tutorial-install-phpmyadmin-on-your-raspberry-pi/

Asignar IP estática (fija) Raspberry Pi

Para saber siempre la IP de tu Raspberry Pi lo que debes hacer es asignarle una IP que tú le especifiques, para ello debemos modificar el archivo «interfaces» de la Raspberry.
Primero podemos hacer una copia del archivo por seguridad:

sudo cp /etc/network/interfaces /etc/network/interfaces_BK

Y ahora modificamos el archivo:

sudo nano /etc/network/interfaces

Dentro del documento yo he tenido que comentar la siguiente línea(puede que en vez de la palabra «manual» aparezca otra):

iface eth0 inet manual

Y Añadir:
-La línea con la palabra «static»
-La dirección que queremos asignarle (en el ejemplo 192.168.1.100)
-La Mascara de red (255.255.255.0)
-La dirección del router (192.168.0.1)

#iface eth0 inet manual
iface eth0 inet static
address 192.168.0.100
netmask 255.255.255.0
gateway 192.168.0.1

La parte anterior sirve para la conexión por cable, si también conectamos la Raspberry por Wifi deberemos hacer lo mismo para la Wifi en el documento, un poquito más abajo:

#iface wlan0 inet manual
iface wlan0 inet static
address 192.168.0.100
netmask 255.255.255.0
gateway 192.168.0.1

Ahora toca reiniciar y ya se conectará con la IP específica.

Fuentes:
http://raspberryparatorpes.net/instalacion/poner-la-direccin-ip-fija-en-raspbian/

https://adrianhontoria.wordpress.com/2013/12/22/ip-fija-en-tu-raspberry-pi/

Pantalla OLED 4Pin Arduino

Hola, voy a explicar como conectar una pantalla OLED de 4Pins como esta:

oled

Si empezamos por el Software, en primer lugar se deben descargar las librerías (library) de Arduino requeridas que proporciona Adafruit:
https://github.com/adafruit/Adafruit_SSD1306
https://github.com/adafruit/Adafruit-GFX-Library

Si no has instalado ninguna librería de Arduino anteriormente consulta este post donde se explican varias maneras de hacerlo.

Después de instalar las bibliotecas, puedes cargar un ejemplo entrando en Archivo-> Ejemplos-> Adafruit SSD1306-> ssd1306_128x64_i2c

ejemplo

Una vez cargamos el ejemplo yo en mi caso he tenido que modificar la siguiente línea:

 display.begin(SSD1306_SWITCHCAPVCC, 0x3D);  // initialize with the I2C addr 0x3D (for the 128x64)

Cambiando 0x3D por 0x3C

 display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)

Ahora vayamos a la conexión del hardware que se debe hacer de la siguiente manera:

esquema OLED arduino

¡Ojo! Yo en mi Oled tengo el VCC y el GND cambiados de sitio, no os fijéis en la posición y fijaros en la palabra que aparece en vuestra OLED.

OLED -> ARDUINO
VCC -> 5V
GND -> GND
SCL -> SCL
SDA -> SDA

¡Ya hemos terminado!

Finalmente si subimos el ejemplo al Arduino podremos ver el resultado.

Fuentes:

 

Importar librerías (library) Arduino

Hay tres maneras de importar una librerías (library) a Arduino:
-Utilizando el Library Manager
-Importando un .zip
-Manualmente

Utilizando el Library Manager
Dentro del menú Programa->Include Library-> Manage Libraries.
Aquí podrás buscar e instalar la librería que quieras.

Importando un .zip
Si tienes un comprimido que te has descargado puedes importar directamente este archivo desde Programa-> Include Library -> Add .zip Library y seleccionar el .zip.

Manualmente
Deberás dejar la carpeta con el contenido (archivo .cpp, archivo .h y otros archivos/caretas como ejemplos) dentro de una determinada carpeta dependiendo de tu SO:

En Windows (carpeta Mis Documentos):
Documentos\Arduino\libraries

En Mac:
Documents/Arduino/libraries

En Linux:
Será la carpeta «libraries» en tu sketchbook.

¡Importante!
Los archivos .cpp y .h se deben encontrar en la carpeta inmediata, no funciona si se encuentran en una subcarpeta, es decir, esta disposición és incorrecta:
Arduino\libraries\Librerias_nuevas\MinuevaLib\archivo.cpp

Debe estar en el primer nivel por debajo de «libraries»:
Arduino\libraries\MinuevaLib\archivo.cpp

Fuentes:
https://www.arduino.cc/en/Guide/Libraries

https://learn.adafruit.com/arduino-tips-tricks-and-techniques/arduino-libraries