Base de Datos Códigos Postales España Julio 2023

Formato: Zip con export MySql

Estructura tablas (Vías, Pseudovías, Tramos y Unidades Poblacionales) descrita en INE – Productos y Servicios – Callejero Censo Electoral

Codigos Postales España Pangodream.es

Talend Open Studio + JRE Error

I’ve just installed TOS 8 on my Windows 10 machine, and after trying to execute it an error appears (I wonder if some day a program running Java not bundled will work at first after being installed):

After installing the latest JDK version, it always throughs the same error.

No matter the times you install/uninstall JDKs, change environment variables, try to launch an inexistent Java Control Panel: always the same error.

The solution
  • Go to Start Button in Windows
  • Locate the TOS Menu
  • Open TOS Menu and right-click on icon launcher
  • Click on More
  • Click on Open File Location
  • Right-Click the Link File and click on Properties
  • Change the Destination folder to the one containing your Java binaries

ESP32 OTA in AP mode: ESP2SOTA

If you are trying to implement OTA functionality for your ESP32 / ESP8266 with AP Wifi Mode enabled, try this simple Arduino Library:

ESP2SOTA Library - ESP32 OTA in AP Mode

Library link: Github Repository

You can also install the library directly from Arduino IDE. Just click on Library Manager and search for ESP2SOTA

By installing the library, two code samples will be available, one for AP Mode and the other one for Client Mode

Sample sketch:

#include <WiFi.h>
#include <WiFiAP.h>
#include <WebServer.h>
/* INCLUDE ESP2SOTA LIBRARY */
#include <ESP2SOTA.h>

const char* ssid = "ESP2SOTA";
const char* password = "123456789abc";

WebServer server(80);

void setup(void) {
  Serial.begin(115200);
  WiFi.mode(WIFI_AP);  
  WiFi.softAP(ssid, password);
  delay(1000);
  IPAddress IP = IPAddress (10, 10, 10, 1);
  IPAddress NMask = IPAddress (255, 255, 255, 0);
  WiFi.softAPConfig(IP, IP, NMask);
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);

  /* SETUP YOR WEB OWN ENTRY POINTS */
  server.on("/myurl", HTTP_GET, []() {
    server.sendHeader("Connection", "close");
    server.send(200, "text/plain", "Hello there!");
  });

  /* INITIALIZE ESP2SOTA LIBRARY */
  ESP2SOTA.begin(&server);
  server.begin();
}

void loop(void) {
  /* HANDLE UPDATE REQUESTS */
  server.handleClient();

  /* YOUR LOOP CODE HERE */


  
  delay(5);
}

HeidiSQL CREATE FUNCTION errors

No matter how simple you define your function, its creation will fail when using HeidiSQL interface.

CREATE FUNCTION `fn_my_function`(
    `parameter_a` INT
)
RETURNS INT
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
   return 0; 
END

HeidiSQL Create Function Error

After reviewing your code, you can’t find any syntax error. You try to fix it by removing the COMMENT ” line, but nothing seems to work.

The solution is quite simple:

  • Tell the SQL engine a new DELIMITER:
    • DELIMITER //
  • After the END; line, add another one to restore the DELIMITER to ;
    • DELIMITER ;
  • That’s all
DELIMITER //

CREATE FUNCTION `fn_my_function`(
    `parameter_a` INT
)
RETURNS INT
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
   return 0; 
END

DELIMITER ;

Please note that there is a space separator between DELIMITER and ;

Laravel 8 + Socialite + Google Login = Error with no message

After struggling for three hours, and making a useless bunch of changes in my code and server configuration, I finally found the solution to this:

  • When you finish your coding, and test it in your localhost deployment, you can login using Google and there’s no problem in getting all the user profile information.
  • Then you deploy the application in your cloud server environment and a “no message” error appears and doesn’t allow you to log into your application.
  • Laravel Socialite Google Login Error with No Message
    Laravel Socialite Google Login Error with No Message

     

MigBuilder: a tool to generate Laravel’s Eloquent files

MigBuilder is a tool to reverse engineer a MySQL database into Models, Factories, Seeders & Migrations files for Laravel Eloquent ORM.

 

MigBuilder is a tool to reverse engineer a MySQL database into Models, Factories, Seeders & Migrations files for Laravel Eloquent ORM.

It reads the database structure and completes as much code as possible to ease the model generation in Laravel.

Unless the model is structured exactly as expected, the code files will contain non accurate lines or declarations. So it is ALWAYS recommended to check the code once is generated.

The ‘perfect’ tables definition is:

  • Tables should contain a single column primary key, better if its name is ‘id’
  • Relationships have to be declared and always be composed of one single column
  • Not frequent datatypes (binary, longtext, …) have not been tested yet
INSTALLATION

composer require pangodream/migbuilder

USAGE

php artisan migbuilder originschema

Migbuilder will read originschema database (originschema is the connection name in Laravel config/app.php file) and will generate the migration, model, seeder and factory files for each of the tables A good practice is two have two different connections declared in Laravel config/database.php file:

  • One alternative connection pointing to the existing database to be reverse engineered
  • The main connection that will be used to deploy migrate files and use models in

CAUTION: If you use the command above and any of the generated files already exists, the generation will not begin unless you specify the overwrite (–overwrite) parameter. Notice that using overwrite will destroy the information you have in any of your files having the same name.

NOTE: Migbuilder is not an error free code generator, but a help to save hand code lines, so you should review the generated code in every case.

I hope it to help you and if you have any comment, please let me know.

Sample generated files:

Source DDL

CREATE TABLE product (
id INT(11) NOT NULL,
name VARCHAR(45) NOT NULL DEFAULT '',
slug VARCHAR(45) NOT NULL DEFAULT '',
description VARCHAR(45) NOT NULL DEFAULT '',
price VARCHAR(45) NOT NULL DEFAULT '',
subcategory_id INT(11) NOT NULL DEFAULT '0',
brand_id INT(11) NOT NULL DEFAULT '0',
quantity VARCHAR(45) NOT NULL DEFAULT '0',
PRIMARY KEY (id),
INDEX FK_products_subcategories (subcategory_id),
INDEX FK_products_brands (brand_id),
CONSTRAINT FK_products_brands FOREIGN KEY (brand_id) REFERENCES brand (id),
CONSTRAINT FK_products_subcategories FOREIGN KEY (subcategory_id) REFERENCES subcategory (id)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

Migration file

<?php
/* Generated automatically using MigBuilder by Pangodream */

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateProductTable extends Migration
{
        
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('product', function (Blueprint $table) {
            $table->id('id');
            $table->string('name', 45)->default('');
            $table->string('slug', 45)->default('');
            $table->string('description', 45)->default('');
            $table->string('price', 45)->default('');
            $table->unsignedBigInteger('subcategory_id')->default(0);
            $table->unsignedBigInteger('brand_id')->default(0);
            $table->string('quantity', 45)->default('0');
            $table->timestamps();

            // Indexes
            $table->index('id');

            // Constraints & Foreign Keys
            $table->foreign('subcategory_id')->references('id')->on('subcategory');
            $table->foreign('brand_id')->references('id')->on('brand');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::disableForeignKeyConstraints();
        Schema::dropIfExists('product');
        Schema::enableForeignKeyConstraints();
    }

}

Model file

<?php
/* Generated automatically using MigBuilder by Pangodream */

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use HasFactory;
    protected $table = 'product';

    // Fillables (remove the columns you don't need)
    protected $fillable = ['id', 'name', 'slug', 'description', 'price', 'subcategory_id', 'brand_id', 'quantity', ];

    // Parent relationships (change belongsTo to belongsToMany or similar if needed)
    public function Subcategory(){
        return $this->belongsTo(Subcategory::class);
    }
    public function Brand(){
        return $this->belongsTo(Brand::class);
    }
    // Child relationships (change hasMany to hasOne or similar if needed)
    public function ColorProduct(){
        return $this->hasMany(ColorProduct::class);
    }
    public function Size(){
        return $this->hasMany(Size::class);
    }

}

Seeder file

<?php
/* Generated automatically using MigBuilder by Pangodream */

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\Product;

class ProductSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
    // Record sample structure
    $product = [
        //'id' =>  ,
        //'name' => '',
        //'slug' => '',
        //'description' => '',
        //'price' => '',
        //'subcategory_id' =>  ,
        //'brand_id' =>  ,
        //'quantity' => '',
    ];

    }
}

Factory file

<?php
/* Generated automatically using MigBuilder by Pangodream */

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Product;

class ProductFactory extends Factory
{
    protected $model = Product::class;
    /**
     * Define the model's default state.
     *
     * @return array
     */
    public function definition()
    {
        return [
            //
        ];
    }
}

Callejero español 2020 con códigos postales (gratis)

Nueva base de actualizada a Julio 2023 en https://www.pangodream.es/base-de-datos-codigos-postales-espana-julio-2023

En determinadas ocasiones necesitamos utilizar información geográfica en nuestras aplicaciones. No me refiero tanto a coordenadas geográficas sino simplemente a disponer de una relación de provincias, municipios, distritos, calles y códigos postales.

Desafortunadamente en España parece que los datos de dominio público se encuentran en un estado de disponibilidad muy precario y que cualquier oportunidad es buena para arañar unos cuantos euros a quien esté dispuesto a pagar por ellos.

Ayer tuve la necesidad de incluir información de este tipo en una de mis aplicaciones y cuál fue mi sorpresa cuando al ir a buscarla a internet para adaptarla me encontré con que aparentemente era información ‘de pago’.

En una búsqueda de Google como esta ‘base de datos codigos postales españa‘ aparece como primer resultado un enlace a la página de la empresa Correos en la que nos da instrucciones de cómo acceder a la base de datos de códigos postales previo pago de 687€ (en su versión más básica).

Indagando algo más encontré alguna referencia a reclamaciones realizadas en la página datos.gob.es cuya resolución dice textualmente:

La base de delimitaciones de códigos postales actualmente está sujeta a comercialización. Para adquirir el listado hay que seguir las instrucciones indicadas en la página de CORREOS

Personalmente me parece vergonzoso que este tipo de información esté comercializada por una empresa privada que nació con presupuesto público, pero España es así.

Dejando polémicas a un lado, seguí buscando y encontré una alternativa muy válida en la página del INE. El Callejero del Censo Electoral sirve perfectamente para este propósito ya que contiene información de todos los municipios de España con sus tramos de vías y pseudovías identificados con su correspondiente código postal. En la página de referencia existe un documento con la especificación de formato de cada uno de los ficheros que contienen la información:

  • Tramos de vía
  • Unidades poblacionales
  • Vías
  • Pseudovías

He realizado una importación y tratamiento de los ficheros para MySQL dejando únicamente la información esencial para poder montar un callejero con información de códigos postales.

La base de datos está disponible aquí. Una vez descomprimida ocupa 164MB.

Tras ejecutar el script SQL, encontraremos una base de datos llamada codpos que contendrá las siguientes tablas:

  • provincia
  • unidad_poblacional
  • via
  • pseudovia
  • tramo

Tramo es la tabla que relaciona el resto y corresponde a los tramos de vía correspondientes a cada una de las secciones y subsecciones censales (información que he omitido de la base de datos).

Un ejemplo de utilización sería la siguiente SQL:

select t.cpro as `codigo_provincia`,
       pr.dpro as `provincia`,
       up.dmun as `municipio`,
       up.nentsic,
       up.nnucle,
       ifnull(pv.dpsvia, concat(v.tvia, ' ', v.nvia)) as `via`,
		 t.cpos as `codigo_postal`
from tramo t left outer join via v 
on(t.cpro = v.cpro and t.cmum = v.cmum and t.cvia = v.cvia)
left outer join pseudovia pv 
on(t.cpro = pv.cpro and t.cmum = pv.cmum and t.cpsvia = pv.cpsvia)
left outer join unidad_poblacional up 
on(t.cpro = up.cpro and t.cmum = up.cmum and t.cun = up.cun)
left outer join provincia pr
on(t.cpro = pr.cpro)
where v.nvia like 'velazquez%'
  and 58 between t.ein and t.esn
  and pr.cpro = 28
  and t.tinum = 2

que nos devolverá todos aquellos tramos de vía con denominación que empiece por ‘velazquez’, que contengan un número 58 entre sus pares (tinum = 2) y que estén en la provincia de Madrid (28).

Read a Xiaomi Mi Smart scale using an ESP32

Xiaomi Mi Smart is a digital scale with BLE interface. This allows it to broadcast your weight to any device like your smart phone and incorporate the measurements to an application like Samsung Health.

Xiaomi Mi Smart Scale

 Two years ago I was trying to read BLE messages from an ESP32, but Arduino BLE libraries didn’t work very well at that moment and all I got were some headaches. I wasn’t even able to match the Weight Measurement remote characteristic, so once the ESP32 connected to the scale it wasn’t able to implement the callback functions.

Today I’ve tried again, and I made it work!!!

Calculate the UUIDs

I have used the BLE_Client example (under ESP32 dev board samples).  In order to connect and read values from any device you need two unique identifiers (16 bit UUID alias):

Now, with this two short uuids, we will calculate the long (128 bits) uuid by using the next formula:

128bit_base_uuid = 16bit_uuid_alias * 2^96 + Bluetooth_Base_UUID

where the Bluetooth_Base_UUID is 1000800000805F9B34FB (00000000-0000-1000-8000-00805F9B34FB)

In our case we will be using the string version of the 128bit uuid and that means all we have to do to calculate the long uuid for the service and the characteristic is concatenating the uuids (aliases and Bluetooth Base one) in the following way:

  • Service UUID: 0000181D-0000-1000-8000-00805F9B34FB
  • Characteristic UUID: 00002A9D-0000-1000-8000-00805F9B34FB
Finding our weight scale

Bring your Xiaomi scale next to your ESP32 MCU and load the next sketch using Arduino IDE:

/**
 * An ESP32 BLE client to find Xiaomi Mi Smart weight scale
 * Author Pangodream
 * Date 2020.05.31
 */

#include "BLEDevice.h"
//Base UUIDs
//Weight Scale service
static BLEUUID srvUUID("0000181d-0000-1000-8000-00805f9b34fb");

/**
 * Callback class for each advertised device during scan
 */
class deviceCB: public BLEAdvertisedDeviceCallbacks {
 //Called on each advertised device
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    // We have found a device, let us now see if it contains the service we are looking for.
    if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(srvUUID)) {
      if(advertisedDevice.getName() != "MI_SCALE"){
        Serial.print("Weight scale (no MI_SCALE) device found with address ");
        Serial.print(advertisedDevice.getAddress().toString().c_str());
        Serial.print(" and name ");
        Serial.println(advertisedDevice.getName().c_str());
      } else {
        Serial.print("Xiaomi Mi Smart weight scale found with address ");
        Serial.println(advertisedDevice.getAddress().toString().c_str());
        BLEDevice::getScan()->stop();
        Serial.println("End of scan");
      }
    } else {
      Serial.print("Non weight scale device found with address ");
      Serial.println(advertisedDevice.getAddress().toString().c_str());
    }
  } 
};

void setup() {
  Serial.begin(115200);
  Serial.println("Devices scan");
  BLEDevice::init("");
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new deviceCB());
  pBLEScan->setInterval(1349);
  pBLEScan->setWindow(449);
  //Set active scan
  pBLEScan->setActiveScan(true);
  //Scan during 5 seconds
  pBLEScan->start(5, false);
}

void loop() {

  delay(1000);
}

The sketch starts an active scan to find all the BLE servers (devices) that are advertising themselves at that moment.

The scan results are shown at the Serial Monitor (115200 bauds) and if a Xiaomi Mi Smart scale is found (and its name is MI_SCALE) something like the next should appear in your monitor:

If your weight scale was present in the scan and you can read the message “Xiaomi Mi Smart weight scale found with address xx:xx:xx:xx:xx:xx” then you can continue with our next goal, which is to retrieve data from weight measurement.

Retrieving data

When the ESP32 is scanning for devices, it only reads the service beacons sent by each BLE server to advertise itself, but when we use the scale and it broadcasts the calculated weight, it doesn’t send the same type of message (it is not a service message, but a characteristic one).

Note that we haven’t used yet the characteristic UUID we calculated before and we’ve only used the service one.

Let’s load a new sketch into the ESP32 MCU to retrieve some data from the characteristic:

/**
 * An ESP32 BLE client to retrieve data from the Weight Measurement characteristic  
 * of a Xiaomi Mi Smart weight scale
 * Author Pangodream
 * Date 2020.05.31
 */

#include "BLEDevice.h"
//Base UUIDs
//Weight Scale service
static BLEUUID srvUUID("0000181d-0000-1000-8000-00805f9b34fb");
//Weight Measurement characteristic
static BLEUUID chrUUID("00002a9d-0000-1000-8000-00805f9b34fb");

static BLEAdvertisedDevice* scale;
static BLERemoteCharacteristic* remoteChr;
static boolean doConnect = false;
static boolean connected = false;
static int year = 0;

/**
 * Callback function for characteristic notify / indication
 */
static void chrCB(BLERemoteCharacteristic* remoteChr, uint8_t* pData, size_t length, bool isNotify) {
    //Console debugging
    Serial.print("Received data. Length = ");
    Serial.print(length);
    Serial.print(". - Data bytes: ");
    for(int i =0; i< length; i++){
      Serial.print(pData[i]);
      Serial.print("  ");
    }
    Serial.println(" ");
    //End of console debugging
    
    //Parsing the received data and calculate weight
    boolean temporary = true;
    int rcvdYear = pData[3];
    //If we received a year for the first time, store it in the year variable
    //The first year we receive indicates a temporary measurement
    if(year == 0){
      year = rcvdYear;
    }else{
      //If year has been previously defined and the year we have received is
      //greater than it, then the measurement is not temporary, is the final one
      if(rcvdYear > year){
        temporary = false;
      }
    }
    double weight = 0;
    weight = (pData[1] + pData[2] * 256) * 0.005;
    
    Serial.print("Weight: ");
    Serial.print(weight);
    Serial.print(" Kg - ");
    if(temporary){
      Serial.println(" (Provisional)");
    }else{
      Serial.println(" (Definitive)");
    }
}

/**
 * Callback class for each advertised device during scan
 */
class deviceCB: public BLEAdvertisedDeviceCallbacks {
 //Called on each advertised device
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    // We have found a device, let us now see if it contains the service we are looking for.
    if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(srvUUID)) {
      if(advertisedDevice.getName() != "MI_SCALE"){
        Serial.print(".");
      } else {
        Serial.println("  Found!");
        BLEDevice::getScan()->stop();
        Serial.println("Stopping scan and connecting to scale");
        scale = new BLEAdvertisedDevice(advertisedDevice);
        doConnect = true;
      }
    } else {
      Serial.print(".");
    }
  } 
};
/**
 * Callback class for device events
 */
class ClientCB : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {

  }

  void onDisconnect(BLEClient* pclient) {
    Serial.println("Disconnected. Reconnecting...");
    connected = false;
  }
};

bool connectToScale() {
    Serial.println("Stablishing communications with scale:");
    BLEClient*  pClient  = BLEDevice::createClient();
    Serial.println("    BLE client created");

    pClient->setClientCallbacks(new ClientCB());

    // Connect to the remove BLE Server.
    pClient->connect(scale);
    Serial.println("    Connected to scale");

    // Obtain a reference to the service we are after in the remote BLE server.
    BLERemoteService* pRemoteService = pClient->getService(srvUUID);
    if (pRemoteService == nullptr) {
      Serial.println("    Error: Failed to find service");
      pClient->disconnect();
      return false;
    }
    Serial.println("    Service found");

    remoteChr = pRemoteService->getCharacteristic(chrUUID);
    if (remoteChr == nullptr) {
      Serial.print("    Failed to find characteristic");
      pClient->disconnect();
      return false;
    }
    Serial.println("    Characteristic found");
    Serial.println("    Setting callback for notify / indicate");
    remoteChr->registerForNotify(chrCB);
    return true;
}

void setup() {
  Serial.begin(115200);
  Serial.println("Searching for MI_SCALE device");
  BLEDevice::init("");
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new deviceCB());
  pBLEScan->setInterval(1349);
  pBLEScan->setWindow(449);
  //Set active scan
  pBLEScan->setActiveScan(true);
  //Scan during 5 seconds
  pBLEScan->start(5, false);
}

void loop() {
  if(doConnect && !connected){
    connected = connectToScale();
  }
  delay(1000);
}

Reboot the MCU and take a look to the serial monitor. If everything goes right, something similar to this should be shown:

The sketch performs these tasks:

  1. Scan devices to find the Xiomi scale
  2. Connects to the scale
  3. Search for the Weight Scale service
  4. Instantiates the service
  5. Search for the remote characteristic
  6. Instantiates the remote characteristic
  7. Sets the callBack function for the characteristic

In this way, when the scale begins to measure weight, our callback function will be invoked receiving the data.

At this point, the ESP32 is waiting to receive something in the callBack function. Put some weight over the scale and you should see the provisional and definitive measurements at the serial monitor.

The callback function always receive 10 bytes of information. These bytes can be parsed to get the weight and timestamp values in the following way:

Parsing the XIOMI Scale BLE data

The way we can differentiate between the provisional and the definitive measurements is looking at the year in the timestamp. While measurements are provisional, the scale sends a fake year and not the current one. So, all we hve to do is taking note of the value for the year in the first data packet we receive and then compare to the rest of the years we receive.

When the received year is greater than the first year we received that is the definitive measurement and we can get the calculated weight.

Why BLE_client sketch doesn’t work

If yoy try the sketch located at File / Examples / ESP32 BLE Arduino / BLE Client it won’t work and will not receive any chararteristic message even when you change the UUIDs.

The reason is this piece of code

if(pRemoteCharacteristic->canNotify())
      pRemoteCharacteristic->registerForNotify(notifyCallback);

To set the callback function for the remote characteristic, first it checks the characteristic can be notifiable (method canNotify()) and our characteristic is not.

If you study the BLE connection using any app for that purpose (I use nRF Connect from Nordic Semiconductor) you will notice that the characteristic we are using is not notifiable but ‘indicate’ type:

So, if you comment out the condition to avoid checking if the characteristic is notifiable or not, and set the callback function anyway, you will received calls in the callback function with the parameter isNotify set to false.

ESP32 MCU + MAX30100 not working

First of all, please read the post title. This doesn’t work on an ESP32 MCU.

I only made it work on an ESP8266 MCU.

This afternoon I received a couple of MAX30100 sensors that I ordered some days before (44 days, China, COVID19, …)

MAX30100 Sensor Board
MAX30100 Sensor Board

The board is quite easy to connect: it has an I2C interface and you even don’t need the INT pin, so all you have to do is wiring the SDA and SCL pins.

I used D22 and D21 pins in my ESP32 MCU, as they are also used for I2C_SDA and I2C_SCL interfacing (checkout pinout diagram here)

Summarizing, the pins you need to connect are:

ESP32 GND to SENSOR GND

ESP32 3.3 to SENSOR VIN

ESP32 D22 to SENSOR SDA

ESP32 D21 to SENSOR SCL

Once you have all the pins connected it’s software time. 

In Arduino IDE, select Manage Libraries and install the Sparkfun MAX3010X Library

Sparkfun MAX3010X Library

After that, you are ready to open any of the examples provided with the library and test the module.

Probably you will notice that doesn’t work correctly. It seems to initialize the module correctly and even it starts to make some measurements. You even  would think that is working for a few seconds, but it isn’t.

The behaviour, at least in my case, is the next: 

  • The module initialize with a SUCESS status
  • It lights on the red led
  • You put your finger over the sensor
  • It starts measuring, but after a second the red led goes off
  • It seems to measure intermittently

If this is your case, don’t waste your time. I was searching for troubleshootings and all I found was replacing the inbuilt 4K7 resistors or bypassing the voltage limiter in the sensor board. Don’t do it, it is not a problem of pull-up resistors.

I decided then to try with an ESP8266 MCU and this is the result:

The sensor board works fine, so probably it is a problem of compatibility between the library and ESP32.

The sensor measures heart rate and SpO2. I only used the heartBeat event to light the led to show that it works.