Categories

Follow

MAX30102 pulse and heart-rate monitor sensor and ESP8266

The MAX30102 is an integrated pulse oximetry and heart-rate monitor biosensor module. It includes internal LEDs, photodetectors, optical elements, and low-noise electronics with ambient light rejection. The MAX30102 provides a complete system solution to ease the design-in process for mobile and wearable devices.

The MAX30102 operates on a single 1.8V power supply and a separate 5.0V power supply for the internal LEDs. Communication is through a standard I2C-compatible interface. The module can be shut down through software with zero standby current, allowing the power rails to remain powered at all times.

Key Features

Heart-Rate Monitor and Pulse Oximeter Biosensor in LED Reflective Solution
Tiny 5.6mm x 3.3mm x 1.55mm 14-Pin Optical Module
Integrated Cover Glass for Optimal, Robust Performance
Ultra-Low Power Operation for Mobile Devices
Programmable Sample Rate and LED Current for Power Savings
Low-Power Heart-Rate Monitor (< 1mW)
Ultra-Low Shutdown Current (0.7µA, typ)
Fast Data Output Capability
High Sample Rates
Robust Motion Artifact Resilience
High SNR
-40°C to +85°C Operating Temperature Range

 

Parts List

This module will cost less than $2

Amount Part Type
1 MAX30102
1 D1 mini V2

 

Schematics/Layout

 

esp8266 and max30102

esp8266 and max30102

Code

Again we use a library and again its an sparkfun one – https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library

 

 

#include <Wire.h>
#include "MAX30105.h"
 
#include "heartRate.h"
 
MAX30105 particleSensor;
 
const byte RATE_SIZE = 4; //Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE]; //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0; //Time at which the last beat occurred
 
float beatsPerMinute;
int beatAvg;
 
void setup()
{
Serial.begin(115200);
Serial.println("Initializing...");
 
// Initialize sensor
if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
{
Serial.println("MAX30105 was not found. Please check wiring/power. ");
while (1);
}
Serial.println("Place your index finger on the sensor with steady pressure.");
 
particleSensor.setup(); //Configure sensor with default settings
particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running
particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED
}
 
void loop()
{
long irValue = particleSensor.getIR();
 
if (checkForBeat(irValue) == true)
{
//We sensed a beat!
long delta = millis() - lastBeat;
lastBeat = millis();
 
beatsPerMinute = 60 / (delta / 1000.0);
 
if (beatsPerMinute < 255 && beatsPerMinute > 20)
{
rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array
rateSpot %= RATE_SIZE; //Wrap variable
 
//Take average of readings
beatAvg = 0;
for (byte x = 0 ; x < RATE_SIZE ; x++)
beatAvg += rates[x];
beatAvg /= RATE_SIZE;
}
}
 
Serial.print("IR=");
Serial.print(irValue);
Serial.print(", BPM=");
Serial.print(beatsPerMinute);
Serial.print(", Avg BPM=");
Serial.print(beatAvg);
 
if (irValue < 50000)
Serial.print(" No finger?");
 
Serial.println();
}

 

 

 

Output

Open the serial monitor – this is what I saw, it took a little bit of time for the readings to appear

IR=110798, BPM=93.46, Avg BPM=74
IR=110791, BPM=93.46, Avg BPM=74
IR=110879, BPM=93.46, Avg BPM=74
IR=110899, BPM=93.46, Avg BPM=74
IR=110969, BPM=93.46, Avg BPM=74
IR=111070, BPM=93.46, Avg BPM=74
IR=111021, BPM=93.46, Avg BPM=74
IR=110997, BPM=93.46, Avg BPM=74
IR=111116, BPM=93.46, Avg BPM=74

 

Links

https://datasheets.maximintegrated.com/en/ds/MAX30102.pdf

Low Power MAX30102 Heart Rate Oxygen Pulse Breakout for Arduino

PAJ7620 gesture sensor and ESP8266

The PAJ7620 integrates gesture recognition function with general I2C interface into a single chip forming an image analytic sensor system. It can recognize 9 human hand gesticulations such as moving up, down, left, right, forward, backward, circle-clockwise, circle-counter clockwise, and waving.

It also offers built-in proximity detection in sensing approaching or departing object from the sensor. The PAJ7620 is designed with great flexibility in power-saving mechanism, well suit for low power battery operated HMI devices.

The PAJ7620 is packaged into module form in-built with IR LED and optics lens as a complete sensor solution.

Gesture Mode : Single-Object Detection
Image Array Size : 60 x 60
Sampling Rate : 240fps
Operating Distance : 20cm
Output Types : 9 types of Gestures: Up, Down, Left, Right, Forward, Backward, Circle-Clockwise, Circle-Counter Clockwise, and Waving)
Cursor Mode : Yes
Interface : I2C/SPI
Light Source : Integrated IR LED with optics

 

Schematics/Layout

esp8266 and PAJ7620

esp8266 and PAJ7620

 

Code

 

Again we use a library – https://www.elecrow.com/wiki/images/7/72/Paj7620.zip

 

 

#include <Wire.h>
#include "paj7620.h"
 
void setup()
{
Serial.begin(9600);
paj7620Init();
}
 
void loop()
{
uint8_t data = 0; // Read Bank_0_Reg_0x43/0x44 for gesture result.
 
paj7620ReadReg(0x43, 1, &data);
 
if (data == GES_UP_FLAG)
{
Serial.println("GES_UP_FLAG !");
}
 
if (data == GES_DOWN_FLAG)
{
Serial.println("GES_DOWN_FLAG !");
}
 
if(data == GES_FORWARD_FLAG)
{
Serial.println("GES_FORWARD_FLAG !");
}
 
if(data == GES_BACKWARD_FLAG)
{
Serial.println("GES_BACKWARD_FLAG !");
}
 
if(data == GES_RIGHT_FLAG)
{
Serial.println("GES_RIGHT_FLAG !");
}
 
if(data ==GES_LEFT_FLAG)
{
Serial.println("GES_LEFT_FLAG !");
}
 
}

 

 

 

Output

Open the serial monitor – this is what I saw, move your hands in various directions

INIT SENSOR…
Addr0 =20, Addr1 =76
wake-up finish.
Paj7620 initialize register finished.
GES_LEFT_FLAG !
GES_UP_FLAG !
GES_UP_FLAG !
GES_FORWARD_FLAG !
GES_BACKWARD_FLAG !
GES_UP_FLAG !
GES_UP_FLAG !

 

Links

http://www.pixart.com.tw/upload/PAJ7620U2_GDS_v1.0_29032016_20160623194552.pdf

The Wemos IR controller shield

In this small article we take a look at the IR controller shield, this is a shield which can act as an IR receiver and sender, here are some details about the shield

  • 1x IR receiver (38kHz)
  • Configurable IO (Default: Sender – D3/GPIO0, Receiver – D4/GPIO2)

Lets see a picture of the shield, you can see the IR reciever and the 4 emitters around the outside, so quite a good design this.

 

The shield uses the follwoing pins, so they would be unavailable for other devices that you use

D1 mini Shield
D3 Send
D4 Receiver

 

Code

You need to install the IRremote ESP8266 Library first. There are a few test examples but i simply wanted to see the code returned from a keypress. The default test examples had a bit more data than I really wished.

I have also noticed false codes getting returned at times, I have not figured this out yet. Looking at possible solutions although a few mention capacitors and noise.

#ifndef UNIT_TEST
#include <Arduino.h>
#endif
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRutils.h>
#if DECODE_AC
#include <ir_Daikin.h>
#include <ir_Fujitsu.h>
#include <ir_Gree.h>
#include <ir_Haier.h>
#include <ir_Kelvinator.h>
#include <ir_Midea.h>
#include <ir_Toshiba.h>
#endif  // DECODE_AC
 
#define RECV_PIN D4
#define BAUD_RATE 115200
#define CAPTURE_BUFFER_SIZE 1024
 
 
#if DECODE_AC
#define TIMEOUT 50U  
#else  
#define TIMEOUT 15U  // Suits most messages, while not swallowing many repeats.
#endif  
 
#define MIN_UNKNOWN_SIZE 12
 
 
// Use turn on the save buffer feature for more complete capture coverage.
IRrecv irrecv(RECV_PIN, CAPTURE_BUFFER_SIZE, TIMEOUT, true);
 
decode_results results;  // Somewhere to store the results
 
 
void setup() 
{
  Serial.begin(BAUD_RATE, SERIAL_8N1, SERIAL_TX_ONLY);
  while (!Serial)  // Wait for the serial connection to be establised.
    delay(50);
  Serial.println();
  Serial.print("IRrecvDumpV2 is now running and waiting for IR input on Pin ");
  Serial.println(RECV_PIN);
 
#if DECODE_HASH
  // Ignore messages with less than minimum on or off pulses.
  irrecv.setUnknownThreshold(MIN_UNKNOWN_SIZE);
#endif  // DECODE_HASH
  irrecv.enableIRIn();  // Start the receiver
}
 
 
void loop() 
{
  if (irrecv.decode(&results)) 
  {
    // print() & println() can't handle printing long longs. (uint64_t)
    serialPrintUint64(results.value, HEX);
    Serial.println("");
    irrecv.resume();  // Receive the next value
  }
  delay(200);
}

 

Testing

Go ahead and press various keys on your remote, this is a couple of keys that I tested. They were 3, 4 and 5 and I did press them multiple times this was not bounce or multiple return codes

FF7A85
FF7A85
FF7A85
FF7A85
FF10EF
FF10EF
FF10EF
FF38C7
FF38C7

 

 

Wemos 1.44“ inch TFT LCD shield examples

In this example we look at the 1.44“ inch TFT LCD shield from Wemos. It can display 128×128 resolution and 18-bit color

The TFT is based on an ST7735S driver. Here is a picture of the LCD shield

The shield uses the following pins

D1 mini Shield
RST*(D0/D3/D4)) TFT_RST
D3*(D0/D4/D8) TFT_DC
D4*(D0/D3/D8) TFT_CS
D7 MOSI
D5 SCK
NC*(D0/D3/D4/D8) TFT_LED
*default

 

Code

You need to install the Adafruit_GFX and Adafruit_ST7735 libraries. You can do this in the Arduino libraries

Here are several examples

Example 1

 

#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
 
#define TFT_RST -1
#define TFT_CS D4
#define TFT_DC D3
 
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
 
void setup(void)
{
tft.initR(INITR_144GREENTAB);
tft.setTextWrap(false); // Allow text to run off right edge
tft.fillScreen(ST7735_BLACK);
}
 
void loop(void)
{
tft.fillScreen(ST7735_BLACK);
tft.setCursor(0, 0);
tft.setTextColor(ST7735_BLUE);
tft.setTextSize(2);
tft.println("ESP8266");
tft.setRotation(tft.getRotation() + 1);
delay(3000);
}

 

Example 2

 

//triangles
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
 
#define TFT_RST -1
#define TFT_CS D4
#define TFT_DC D3
 
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
 
void setup(void)
{
tft.initR(INITR_144GREENTAB);
}
 
void loop(void) 
{
tft.fillScreen(ST77XX_BLACK);
int color = 0xF800;
int t;
int w = tft.width()/2;
int x = tft.height()-1;
int y = 0;
int z = tft.width();
for(t = 0 ; t <= 15; t++) 
{
tft.drawTriangle(w, y, y, x, z, x, color);
x-=4;
y+=4;
z-=4;
color+=100;
}
delay(500);
}

 

 

Example 3

 

//round rectangles
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
 
#define TFT_RST -1
#define TFT_CS D4
#define TFT_DC D3
 
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
 
void setup(void)
{
tft.initR(INITR_144GREENTAB);
}
 
void loop(void) 
{
tft.fillScreen(ST77XX_BLACK);
int color = 100;
int i;
int t;
for(t = 0 ; t <= 4; t+=1) 
{
int x = 0;
int y = 0;
int w = tft.width()-2;
int h = tft.height()-2;
for(i = 0 ; i <= 16; i+=1) 
{
tft.drawRoundRect(x, y, w, h, 5, color);
x+=2;
y+=3;
w-=4;
h-=6;
color+=1100;
}
color+=100;
}
delay(500);
}

 

 

Example 4

 

//text examples
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
 
#define TFT_RST -1
#define TFT_CS D4
#define TFT_DC D3
 
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
 
void setup(void)
{
tft.initR(INITR_144GREENTAB);
}
 
void loop(void) 
{
float p = 3.1415926;
tft.setTextWrap(false);
tft.fillScreen(ST77XX_BLACK);
tft.setCursor(0, 30);
tft.setTextColor(ST77XX_RED);
tft.setTextSize(1);
tft.println("Hello World!");
tft.setTextColor(ST77XX_YELLOW);
tft.setTextSize(2);
tft.println("Hello World!");
tft.setTextColor(ST77XX_GREEN);
tft.setTextSize(3);
tft.println("Hello World!");
tft.setTextColor(ST77XX_BLUE);
tft.setTextSize(4);
tft.print(1234.567);
delay(2500);
tft.setCursor(0, 0);
tft.fillScreen(ST77XX_BLACK);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(0);
tft.println("Hello World!");
tft.setTextSize(1);
tft.setTextColor(ST77XX_GREEN);
tft.print(p, 6);
tft.println(" Want pi?");
tft.println(" ");
tft.print(8675309, HEX); // print 8,675,309 out in HEX!
tft.println(" Print HEX!");
tft.println(" ");
tft.setTextColor(ST77XX_WHITE);
tft.println("Sketch has been");
tft.println("running for: ");
tft.setTextColor(ST77XX_MAGENTA);
tft.print(millis() / 1000);
tft.setTextColor(ST77XX_WHITE);
tft.print(" seconds.");
delay(2500);
}

 

 

Example 5

 

//rectangle examples
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
 
#define TFT_RST -1
#define TFT_CS D4
#define TFT_DC D3
 
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
 
void setup(void)
{
tft.initR(INITR_144GREENTAB);
}
 
void loop(void) 
{
tft.fillScreen(ST77XX_BLACK);
//rectangles
for (int16_t x=0; x < tft.width(); x+=6) 
{
tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, ST77XX_WHITE);
}
delay(2500);
//filled rectangles
tft.fillScreen(ST77XX_BLACK);
for (int16_t x=tft.width()-1; x > 6; x-=6) 
{
tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, ST77XX_YELLOW);
tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, ST77XX_MAGENTA);
}
delay(2500);
}

 

 

Example 6

 

//circle examples
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
 
#define TFT_RST -1
#define TFT_CS D4
#define TFT_DC D3
 
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
 
void setup(void)
{
tft.initR(INITR_144GREENTAB);
}
 
void loop(void) 
{
int radius = 10;
tft.fillScreen(ST77XX_BLACK);
//filled circle
for (int16_t x=radius; x < tft.width(); x+=radius*2) 
{
for (int16_t y=radius; y < tft.height(); y+=radius*2) 
{
tft.fillCircle(x, y, radius, ST77XX_YELLOW);
}
}
delay(2500);
//circles
tft.fillScreen(ST77XX_BLACK);
for (int16_t x=0; x < tft.width()+radius; x+=radius*2) 
{
for (int16_t y=0; y < tft.height()+radius; y+=radius*2) 
{
tft.drawCircle(x, y, radius, ST77XX_MAGENTA);
}
}
delay(2500);
}

 

 

Example 7

 

//play button
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
 
#define TFT_RST -1
#define TFT_CS D4
#define TFT_DC D3
 
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
 
void setup(void)
{
tft.initR(INITR_144GREENTAB);
}
 
void loop(void) 
{
tft.fillScreen(ST77XX_BLACK);
tft.fillRoundRect(25, 10, 78, 60, 8, ST77XX_WHITE);
tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_RED);
delay(500);
// play color
tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_BLUE);
delay(500);
// play color
tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_GREEN);
}

 

 

Example 8

 

#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
 
#define TFT_RST -1
#define TFT_CS D4
#define TFT_DC D3
 
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
 
void setup(void)
{
tft.initR(INITR_144GREENTAB);
}
 
void loop(void) 
{
uint16_t color = ST77XX_YELLOW;
tft.fillScreen(ST77XX_BLACK);
for (int16_t x=0; x < tft.width(); x+=6) 
{
tft.drawLine(0, 0, x, tft.height()-1, color);
delay(0);
}
for (int16_t y=0; y < tft.height(); y+=6)
{
tft.drawLine(0, 0, tft.width()-1, y, color);
delay(0);
}
}

 

 

Example 9

 

#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
 
#define TFT_RST -1
#define TFT_CS D4
#define TFT_DC D3
 
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
 
void setup(void)
{
tft.initR(INITR_144GREENTAB);
}
 
void loop(void) 
{
for (uint8_t i=0; i<4; i++) 
{
tft.fillScreen(ST77XX_BLACK);
tft.drawCircle(10, 30, 10, ST77XX_YELLOW);
tft.setRotation(tft.getRotation()+1);
}
delay(500);
for (uint8_t i=0; i<4; i++) 
{
tft.fillScreen(ST77XX_BLACK);
tft.fillRect(10, 20, 10, 20, ST77XX_GREEN);
tft.setRotation(tft.getRotation()+1);
}
delay(500);
}

 

Video

A youtube video we made of  these examples

 

Link

ESP8266 TFT 1.4 Shield V1.0.0 Display Screen Module for D1 mini 1.44″ inch 128X128 SPI LCD ST7735S