|
|
| (37 intermediate revisions by the same user not shown) |
| Line 1: |
Line 1: |
| == Special Libraries ==
| | Being written on the fly, expect rewrites and restructures. Enough information is here for writing code on the completed hardware. |
| <code>
| |
|
| |
|
| <nowiki>#</nowiki>include <Adafruit_GFX.h>
| | = Basic Software Load for Main Device Only. Later Update to Incorporate Port Usage with External Units. = |
|
| |
|
| <nowiki>#</nowiki>include <Adafruit_ST7735.h> | | == Hardware Libraries == |
| | | <nowiki> |
| <nowiki>#</nowiki>include <Adafruit_VL53L0X.h> | | #include <Wire.h> |
| | | #include <SPI.h> |
| <nowiki>#</nowiki>include <Adafruit_AMG88xx.h>
| | #include <Adafruit_GFX.h> |
| | | #include <Adafruit_ST7735.h> |
| <nowiki>#</nowiki>include <MAX30105.h>
| | #include <Adafruit_VL53L0X.h> |
| | | #include <Adafruit_AMG88xx.h> |
| <nowiki>#</nowiki>include <SparkFunMLX90614.h>
| | #include <MAX30105.h> |
| | | #include <SparkFunMLX90614.h> |
| <nowiki>#</nowiki>include <DFRobot_ID809.h>
| | #include <DFRobot_ID809.h> |
| | | #include <SD.h> |
| <nowiki>#</nowiki>include <SD.h>
| | #include <pu2clr_pcf8574.h> |
| | | #include <TCA9548A.h> |
| <nowiki>#</nowiki>include <Adafruit_MPU6050.h>
| | </nowiki> |
| | |
| <nowiki>#</nowiki>include <pu2clr_pcf8574.h>
| |
| | |
| <nowiki>#</nowiki>include <TCA9548A.h>
| |
| | |
| </code> | |
|
| |
|
| == Library Modification == | | == Library Modification == |
| Line 42: |
Line 35: |
|
| |
|
| == Defines - Variables - Routines == | | == Defines - Variables - Routines == |
| Updates Needed
| |
|
| |
|
| The following code is a mixing and matching of the example code provided by the referenced Special Libraries. | | The following code is a mixing and matching of the example code provided by the referenced Special Libraries. |
| ==== Includes ==== | | ==== Custom Includes ==== |
| <nowiki>
| |
| #include <Wire.h>
| |
| #include <SPI.h>
| |
|
| |
|
| #include <Adafruit_GFX.h>
| |
| #include <Adafruit_ST7735.h>
| |
| #include "Adafruit_VL53L0X.h"
| |
| #include <Adafruit_AMG88xx.h>
| |
| #include <MAX30105.h>
| |
| #include <SparkFunMLX90614.h>
| |
| #include <DFRobot_ID809.h>
| |
| #include "bmpHeader.h"
| |
| #include <SD.h>
| |
|
| |
|
| #include "TFT_Stuff.h" | | [[Pseudo-Medical Monitor Code I2CMUX STUFF|#include "I2CMUX_Stuff.h"]] |
| | |
| #include "HB_Stuff.h"
| |
| #include "AMG_Stuff.h"
| |
| #include "VL_Stuff.h"
| |
| #include "CT_Stuff.h"
| |
| #include "FP_Stuff.h"
| |
| #include "EXG_Stuff.h"
| |
| | |
| </nowiki>
| |
| | |
| ==== VL53L0X Sensor (VL_Stuff.h) ====
| |
| <nowiki>
| |
| #define START_DISTANCE 500
| |
| #define EXG_DISTANCE 150
| |
| | |
| Adafruit_VL53L0X lox = Adafruit_VL53L0X();
| |
|
| |
|
| bool EXG_Mode = false;
| | [[Pseudo-Medical Monitor Code TFT STUFF|#include "TFT_Stuff.h"]] |
|
| |
|
| int last_range_measurement = -1;
| | [[Pseudo-Medical Monitor Code SD STUFF|#include "SD_Stuff.h"]] |
| int VL_x_offset = 118;
| |
| int VL_y_offset = 0;
| |
| int VL_x_width = 10;
| |
| int VL_y_height = 74;
| |
|
| |
|
| void setup_VL()
| |
| {
| |
| lox.begin();
| |
| }
| |
|
| |
|
| void VL_Reset()
| |
| {
| |
| last_range_measurement = -1;
| |
| }
| |
|
| |
|
| void range_display(int range_measurement)
| | [[Pseudo-Medical Monitor Code HeartBeat_STUFF|#include "HeartBeat_Stuff.h"]] |
| {
| |
| int box_top = VL_y_offset;
| |
| int box_bottom = box_top + VL_y_height;
| |
|
| |
| int box_left = VL_x_offset;
| |
| int box_right = box_left + VL_x_width;
| |
|
| |
| int box_width = VL_x_width;
| |
| int box_height = VL_y_height;
| |
|
| |
| int bar_top = box_top + 1;
| |
| int bar_bottom = box_bottom - 1;
| |
|
| |
|
| int bar_left = box_left + 1;
| | Two related include files from Library for MAX30105 examples not included here |
| int bar_right = box_right -1;
| | * bmpHeader.h |
| | * Interoplation. |
|
| |
|
| int bar_width = VL_x_width - 2;
| |
| int bar_height = VL_y_height - 2;
| |
|
| |
|
| int bar_measure;
| | [[Pseudo-Medical Monitor Code ThermalImage_STUFF|#include "ThermalImager_Stuff.h"]] |
|
| |
| if (last_range_measurement == -1)
| |
| {
| |
| // Draw Box
| |
| tft.fillRect(box_left, box_top, box_width, box_height, ST7735_BLACK);
| |
| tft.drawRect(box_left, box_top, box_width, box_height, ST7735_YELLOW);
| |
| }
| |
|
| |
| if (last_range_measurement != range_measurement)
| |
| {
| |
| tft.fillRect(bar_left, bar_top, bar_width, bar_height, ST7735_BLACK);
| |
| if (range_measurement > START_DISTANCE)
| |
| tft.fillRect(bar_left, bar_top, bar_width, bar_height, ST7735_RED);
| |
| else
| |
| {
| |
| if (range_measurement < EXG_DISTANCE)
| |
| {
| |
| bar_measure = ((float)range_measurement / (float)START_DISTANCE) * bar_height;
| |
| tft.fillRect(bar_left, bar_bottom - bar_measure, bar_width, bar_measure, ST7735_BLUE);
| |
| }
| |
| else
| |
| {
| |
| bar_measure = ((float)range_measurement / (float)START_DISTANCE) * bar_height;
| |
| tft.fillRect(bar_left, bar_bottom - bar_measure, bar_width, bar_measure, ST7735_GREEN);
| |
| }
| |
| }
| |
| }
| |
|
| |
|
| last_range_measurement = range_measurement;
| | [[Pseudo-Medical Monitor Code TOFLaser_STUFF|#include "TOFLaser_Stuff.h"]] |
| }
| |
|
| |
|
| int VL_Reading()
| | [[Pseudo-Medical Monitor Code NonContactThermometer_STUFF|#include "NonContactThermometer_Stuff.h"]] |
| {
| |
| int range_measure;
| |
|
| |
| VL53L0X_RangingMeasurementData_t measure;
| |
| lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!
| |
| if (measure.RangeStatus != 4)
| |
| { // phase failures have incorrect data
| |
| range_measure = measure.RangeMilliMeter;
| |
| }
| |
| else
| |
| {
| |
| range_measure = 9999;
| |
| }
| |
|
| |
|
| if (range_measure < EXG_DISTANCE)
| | [[Pseudo-Medical Monitor Code FingerPrint_STUFF|#include "FingerPrint_Stuff.h"]] |
| EXG_Mode = true;
| |
| else
| |
| EXG_Mode = false;
| |
|
| |
|
| return(range_measure);
| |
| }
| |
|
| |
|
| void VL_Frame()
| | [[Pseudo-Medical Monitor Code ControlPanel_STUFF|#include "ControlPanel_Stuff.h"]] |
| {
| |
| int range_measure;
| |
|
| |
| range_measure = VL_Reading();
| |
|
| |
| range_display(range_measure);
| |
|
| |
|
| // delay(100);
| | [[Pseudo-Medical Monitor Code AudioBoard_STUFF|#include "AudioBoard_Stuff.h"]] |
| }
| |
| </nowiki>
| |
|
| |
|
| ==== Heart Beat Sensor (HB_Stuff.h) ====
| |
| <nowiki> | | <nowiki> |
|
| |
|
| static const unsigned char PROGMEM still_heart_logo_bmp[] =
| | #include "I2CMUX_Stuff.h" |
| {
| | #include "TFT_Stuff.h" |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
| | #include "SD_Stuff.h" |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x0F, 0x00, 0x00, 0x67, 0x18, 0xC0, 0x00, 0xC1, 0xB0, 0x60,
| |
| 0x01, 0x80, 0xE0, 0x20, 0x01, 0x00, 0xC0, 0x30, 0x01, 0x00, 0x40, 0x10, 0x01, 0x00, 0x40, 0x10,
| |
| 0x01, 0x04, 0x00, 0x10, 0x01, 0x04, 0x00, 0x10, 0x01, 0x0C, 0x00, 0x30, 0x00, 0x88, 0x80, 0x20,
| |
| 0x00, 0x8B, 0x80, 0x40, 0x0F, 0xF3, 0x70, 0x80, 0x00, 0x13, 0x01, 0x80, 0x00, 0x19, 0x03, 0x00,
| |
| 0x00, 0x0C, 0x06, 0x00, 0x00, 0x06, 0x0C, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x01, 0xB0, 0x00,
| |
| 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
| |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
| |
| };
| |
| | |
| static const unsigned char PROGMEM beat_heart_logo_bmp[] =
| |
| {
| |
| 0x01, 0xF0, 0x0F, 0x80, 0x06, 0x1C, 0x38, 0x60, 0x18, 0x06, 0x60, 0x18, 0x10, 0x01, 0x80, 0x08,
| |
| 0x20, 0x01, 0x80, 0x04, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x02, 0xC0, 0x00, 0x08, 0x03,
| |
| 0x80, 0x00, 0x08, 0x01, 0x80, 0x00, 0x18, 0x01, 0x80, 0x00, 0x1C, 0x01, 0x80, 0x00, 0x14, 0x00,
| |
| 0x80, 0x00, 0x14, 0x00, 0x80, 0x00, 0x14, 0x00, 0x40, 0x10, 0x12, 0x00, 0x40, 0x10, 0x12, 0x00,
| |
| 0x7E, 0x1F, 0x23, 0xFE, 0x03, 0x31, 0xA0, 0x04, 0x01, 0xA0, 0xA0, 0x0C, 0x00, 0xA0, 0xA0, 0x08,
| |
| 0x00, 0x60, 0xE0, 0x10, 0x00, 0x20, 0x60, 0x20, 0x06, 0x00, 0x40, 0x60, 0x03, 0x00, 0x40, 0xC0,
| |
| 0x01, 0x80, 0x01, 0x80, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x30, 0x0C, 0x00,
| |
| 0x00, 0x08, 0x10, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00
| |
| };
| |
| | |
| MAX30105 particleSensor;
| |
| | |
| #define HB_INT 4 | |
| | |
| int HB_x_offset = 0;
| |
| int HB_y_offset = 78;
| |
| int HB_x_width = 46;
| |
| int HB_y_height = 82;
| |
| | |
| int HB_initialize_screen = -1;
| |
| | |
| void HB_Reset()
| |
| {
| |
| HB_initialize_screen = -1;
| |
| }
| |
| | |
| void setup_HB()
| |
| {
| |
| // Initialize sensor
| |
| if (!particleSensor.begin()) //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 HB_Frame()
| |
| {
| |
| int box_top = HB_y_offset;
| |
| int box_bottom = box_top + HB_y_height;
| |
|
| |
| int box_left = HB_x_offset;
| |
| int box_right = box_left + HB_x_width;
| |
|
| |
| int box_width = HB_x_width;
| |
| int box_height = HB_y_height;
| |
| | |
| const byte RATE_SIZE = 6; //Increase this for more averaging. 4 is good.
| |
| byte rates[RATE_SIZE]; //Array of heart rates
| |
| long pulse_ir[RATE_SIZE];
| |
| long pulse_red[RATE_SIZE];
| |
|
| |
| byte rateSpot = 0;
| |
| byte O2Spot = 0;
| |
| long O2AVG = 0;
| |
| long lastBeat = 0; //Time at which the last beat occurred
| |
| float beatsPerMinute;
| |
| int beatAvg = -1, lastAvg = 0;
| |
| long irAVG = 0;
| |
| long redAVG = 0;
| |
| | |
| bool beatDetect = false;
| |
| int latentBeatMax = 2;
| |
| int latentBeat = 0;
| |
| | |
| long irValue = 0;
| |
| long redValue = 0;
| |
| long maxValue = 0;
| |
| long lastValue = 0;
| |
| long turnValue = 0;
| |
| long lastMax = 0;
| |
| | |
| int tft_HB_Screen = 0;
| |
| int last_HB_Screen = -1;
| |
|
| |
| unsigned long start_time;
| |
| unsigned long delta = 0;
| |
| int HB_detect_threshold = 7000;
| |
| | |
| // Clear rate calculating array
| |
| for(byte x = 0; x < RATE_SIZE ; ++x)
| |
| rates[x] = 0;
| |
| | |
| if (HB_initialize_screen == -1)
| |
| {
| |
| tft.fillRect(box_left, box_top, box_width, box_height, ST7735_BLACK);
| |
| tft.drawRect(box_left, box_top, box_width, box_height, ST7735_BLUE);
| |
| tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
| |
| tft.setCursor(box_left + 3,box_top + 4);
| |
| tft.println("Place ");
| |
| tft.setCursor(box_left + 3,box_top + 16);
| |
| tft.println("your ");
| |
| tft.setCursor(box_left + 3,box_top + 28);
| |
| tft.println("finger ");
| |
| tft.setCursor(box_left + 3,box_top + 40);
| |
| tft.println("on ");
| |
| tft.setCursor(box_left + 3,box_top + 52);
| |
| tft.println("sensor ");
| |
| HB_initialize_screen = 0;
| |
| for (byte x = 0 ; x < RATE_SIZE ; x++)
| |
| rates[x] = 0;
| |
| }
| |
| | |
| irValue = particleSensor.getIR();
| |
| redValue = particleSensor.getRed();
| |
|
| |
| while(irValue > HB_detect_threshold)
| |
| {
| |
| irValue = particleSensor.getIR(); //Reading the IR value it will permit us to know if there's a finger on the sensor or not
| |
| redValue = particleSensor.getRed();
| |
|
| |
| // Serial.print(irValue);
| |
| // Serial.print(",");
| |
| // Serial.print(redValue);
| |
| // Serial.print(",");
| |
| // Serial.print(maxValue);
| |
| // Serial.print(",");
| |
| // Serial.print(turnValue);
| |
| // Serial.print(",");
| |
| // Serial.print(lastMax);
| |
| Serial.println();
| |
|
| |
| if (irValue > 7000)
| |
| {
| |
| //finger is detected
| |
| tft_HB_Screen = 1;
| |
| if (irValue > maxValue)
| |
| maxValue = irValue;
| |
| | |
| // if ((irValue < maxValue - 200) && (irValue > lastValue + 20)) // alternate detect beat method
| |
| if (irValue < maxValue - 200)
| |
| {
| |
| beatDetect = true;
| |
| lastMax = maxValue;
| |
| maxValue = irValue;
| |
| turnValue = lastValue;
| |
| latentBeat = latentBeatMax;
| |
| }
| |
| | |
| lastValue = irValue;
| |
|
| |
| if (beatDetect == true)
| |
| {
| |
| beatDetect = false;
| |
| | |
| //We sensed a beat!
| |
| delta = millis() - lastBeat; //Measure duration between two beats
| |
| lastBeat = millis();
| |
| | |
| beatsPerMinute = 60 / (delta / 1000.0); //Calculating the BPM
| |
| lastAvg = beatAvg;
| |
| | |
| pulse_ir[O2Spot++] = irValue;
| |
| pulse_red[O2Spot] = redValue;
| |
| /*
| |
| if (O2Spot == RATE_SIZE)
| |
| {
| |
| for (byte x = 0; x < RATE_SIZE; ++x)
| |
| {
| |
| irAVG = irAVG + pulse_ir[x];
| |
| redAVG = redAVG + pulse_red[x];
| |
| }
| |
| O2AVG = ((float)irAVG / (float) redAVG) * 100;
| |
| tft.setCursor(box_left + 4,box_top + 56);
| |
| tft.println(O2AVG);
| |
| O2Spot = 0;
| |
| }
| |
| */
| |
| if ((beatsPerMinute < 255.0) && (beatsPerMinute > 20.0)) //To calculate the average we strore some values (4) then do some math to calculate the average
| |
| {
| |
| 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;
| |
| }
| |
| }
| |
| }
| |
| | |
| | |
| if (irValue < 7000)
| |
| { //If no finger is detected it inform the user and put the average BPM to 0 or it will be stored for the next measure
| |
| tft_HB_Screen = 0;
| |
| beatAvg=0;
| |
| lastAvg = 0;
| |
| for(byte x = 0; x < RATE_SIZE ; ++x)
| |
| rates[x] = 0;
| |
| }
| |
|
| |
| switch(tft_HB_Screen)
| |
| {
| |
| case 0:
| |
| if (last_HB_Screen != 0)
| |
| tft.fillRect(box_left + 1, box_top + 1, box_width - 2, box_height - 2, ST7735_BLACK);
| |
| tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
| |
| tft.setCursor(box_left + 3,box_top + 4);
| |
| tft.println("Place ");
| |
| tft.setCursor(box_left + 3,box_top + 16);
| |
| tft.println("your ");
| |
| tft.setCursor(box_left + 3,box_top + 28);
| |
| tft.println("finger ");
| |
| tft.setCursor(box_left + 3,box_top + 40);
| |
| tft.println("on ");
| |
| tft.setCursor(box_left + 3,box_top + 52);
| |
| tft.println("sensor ");
| |
| break;
| |
| case 1:
| |
| if (last_HB_Screen != 1)
| |
| tft.fillRect(box_left + 1,box_top + 1,32,33,ST7735_BLACK);
| |
| tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
| |
| if (latentBeat == latentBeatMax)
| |
| {
| |
| tft.fillRect(box_left + 1,box_top + 1, box_width - 2, 33, ST7735_BLACK);
| |
| tft.drawBitmap(box_left + 2,box_top + 2, beat_heart_logo_bmp, 32, 32, ST7735_RED); //Draw the second picture (bigger heart)
| |
| }
| |
| if (latentBeat == 0)
| |
| {
| |
| tft.fillRect(box_left + 1,box_top + 1, box_width - 2, 33, ST7735_BLACK);
| |
| tft.drawBitmap(box_left + 2, box_top + 2, still_heart_logo_bmp, 32, 32, ST7735_WHITE); //Draw the first bmp picture (little heart)
| |
| latentBeat = -1;
| |
| }
| |
| if (latentBeat > 0)
| |
| -- latentBeat;
| |
| if (lastAvg != beatAvg)
| |
| {
| |
| tft.fillRect(box_left + 1,box_top + 34 ,box_width - 2,box_height - 35, ST7735_BLACK);
| |
| tft.setCursor(box_left + 4,box_top + 34);
| |
| tft.println("BPM");
| |
| tft.setCursor(box_left + 4,box_top + 44);
| |
| tft.println(beatAvg);
| |
| lastAvg = beatAvg;
| |
| }
| |
| break;
| |
| case 2:
| |
| tft.fillRect(box_left + 1,box_top + 2, 32, 32, ST7735_BLACK);
| |
| tft.drawBitmap(box_left + 2,box_top + 2, beat_heart_logo_bmp, 32, 32, ST7735_RED); //Draw the second picture (bigger heart)
| |
| | |
| tft.fillRect(box_left + 1,box_top + 34 ,box_width - 2,box_height - 35, ST7735_BLACK);
| |
| tft.setCursor(box_left + 4,box_top + 34);
| |
| tft.println("BPM");
| |
| tft.setCursor(box_left + 4,box_top + 44);
| |
| tft.println(beatAvg);
| |
| break;
| |
| case 3:
| |
| break;
| |
| }
| |
| last_HB_Screen = tft_HB_Screen;
| |
| delay(100);
| |
| }
| |
| }
| |
| | |
| </nowiki>
| |
| | |
| ==== Fingerprint Scanner (FP_Stuff.h) ====
| |
| <nowiki>
| |
| #define FPSerial Serial1 | |
| #define FP_INIT 3
| |
| | |
| DFRobot_ID809 fingerprint;
| |
| String desc;
| |
| File myFile;
| |
| | |
| //#define QUARTER
| |
| #ifdef QUARTER
| |
| uint8_t data[6400]; //Quarter image
| |
| #else
| |
| uint8_t data[25600]; //Full image
| |
| #endif
| |
| | |
| int FP_x_offset = 46;
| |
| int FP_y_offset = 78;
| |
| int FP_x_width = 82;
| |
| int FP_y_height = 82;
| |
| | |
| bool fingerprint_captured = false;
| |
| bool FP_first_pass = true;
| |
| | |
| void setup_FP()
| |
| {
| |
| pinMode(FP_INIT,INPUT);
| |
| /*Init FPSerial*/
| |
| FPSerial.begin(115200);
| |
| /*Take FPSerial as communication port of fingerprint module */
| |
| fingerprint.begin(FPSerial);
| |
|
| |
| /*Wait for Serial to open*/
| |
| /*Test whether device can communicate properly with mainboard
| |
| Return true or false
| |
| */
| |
| while(fingerprint.isConnected() == false)
| |
| {
| |
| Serial.println("Communication with device failed, please check connection");
| |
| /*Get error code information */
| |
| desc = fingerprint.getErrorDescription();
| |
| Serial.println(desc);
| |
| delay(1000);
| |
| }
| |
| }
| |
| | |
| | |
| void FP_Reset()
| |
| {
| |
| fingerprint_captured = false;
| |
| FP_first_pass = true;
| |
| }
| |
| | |
| void FP_Frame()
| |
| {
| |
| int box_top = FP_y_offset;
| |
| int box_bottom = box_top + FP_y_height;
| |
|
| |
| int box_left = FP_x_offset;
| |
| int box_right = box_left + FP_x_width;
| |
|
| |
| int box_width = FP_x_width;
| |
| int box_height = FP_y_height;
| |
| | |
| int p_x, p_y, p_i, p_data, p_temp;
| |
|
| |
| if (FP_first_pass)
| |
| {
| |
| tft.drawRect(box_left, box_top, box_width, box_height, ST7735_MAGENTA);
| |
| tft.fillRect(box_left + 1, box_top + 1, box_width - 2, box_height - 2, ST7735_BLACK);
| |
| fingerprint.ctrlLED(/*LEDMode = */fingerprint.eBreathing, /*LEDColor = */fingerprint.eLEDRed, /*blinkCount = */0);
| |
| tft.setCursor(box_left + 4, box_top + 4);
| |
| tft.println("Place Finger");
| |
| tft.setCursor(box_left + 4, box_top + 16);
| |
| tft.println("on scanner.");
| |
| FP_first_pass = false;
| |
| }
| |
| | |
| if ((fingerprint.detectFinger()) && (!fingerprint_captured))
| |
| {
| |
| tft.setCursor(box_left + 4, box_top + 4);
| |
| tft.println("Keep Finger ");
| |
| tft.setCursor(box_left + 4, box_top + 16);
| |
| tft.println("on scanner.");
| |
|
| |
| fingerprint.getFingerImage(data);
| |
| fingerprint.ctrlLED(/*LEDMode = */fingerprint.eKeepsOn, /*LEDColor = */fingerprint.eLEDGreen, /*blinkCount = */0);
| |
| for (p_x=0; p_x < 80; ++p_x)
| |
| for (p_y=0; p_y < 80; ++p_y)
| |
| {
| |
| p_temp = (p_x * 2);
| |
| p_temp = p_temp + (p_y * 160);
| |
| p_data = data[p_temp]/4; // image element
| |
| | |
| p_temp = p_temp + 1;
| |
| p_data = p_data + data[p_temp]/4; // image element to the right
| |
| | |
| p_temp = (p_x * 2);
| |
| p_temp = p_temp + ((p_y + 1) * 160);
| |
| p_data = p_data + data[p_temp]/4; // image element below
| |
| | |
| p_temp = (p_x + 1) * 2;
| |
| p_temp = p_temp + ((p_y + 1) * 160);
| |
| p_data = p_data + data[p_temp]/4; // image element to the right, one element down
| |
|
| |
| p_data = p_data/4;
| |
| tft.drawPixel(box_left+1+p_x,box_top+1+p_y,p_data<<5);
| |
| }
| |
| }
| |
|
| |
| }
| |
| | |
| </nowiki>
| |
| | |
| ==== MLX90614 Sensor Code (CT_Stuff.h) ====
| |
| <nowiki>
| |
| IRTherm therm; // Create an IRTherm object to interact with throughout
| |
| | |
| int last_object_measurement = -1;
| |
| int last_ambient_measurement = -1;
| |
| | |
| int CT_x_offset = 0;
| |
| int CT_y_offset = 0;
| |
| int CT_x_width = 44;
| |
| int CT_y_height = 74;
| |
| | |
| void setup_CT()
| |
| {
| |
| if (therm.begin() == false) { // Initialize thermal IR sensor
| |
| Serial.println("IR thermometer Failed");
| |
| while (1);
| |
| }
| |
| | |
| therm.setUnit(TEMP_F); // Set the library's units to Farenheit
| |
| | |
| }
| |
| | |
| | |
| void CT_Reset()
| |
| {
| |
| last_object_measurement = -1;
| |
| last_ambient_measurement = -1;
| |
| }
| |
| | |
| void CT_Frame()
| |
| {
| |
| int box_top = CT_y_offset;
| |
| int box_bottom = box_top + CT_y_height;
| |
|
| |
| int box_left = CT_x_offset;
| |
| int box_right = box_left + CT_x_width;
| |
|
| |
| int box_width = CT_x_width;
| |
| int box_height = CT_y_height;
| |
| | |
| int ambient_x_offset = box_left + 1;
| |
| int ambient_y_offset = box_top + 8;
| |
| int object_x_offset = box_left + 1;
| |
| int object_y_offset = ambient_y_offset + 20;
| |
| | |
| int ambient_measurement;
| |
| int object_measurement;
| |
| | |
| if ((last_ambient_measurement == -1) && (last_object_measurement == -1))
| |
| {
| |
| tft.drawRect(box_left, box_top, box_width, box_height, ST7735_RED);
| |
| tft.setCursor(ambient_x_offset, ambient_y_offset);
| |
| tft.println("MLX90XX");
| |
| tft.setCursor(object_x_offset, object_y_offset);
| |
| tft.println("Object");
| |
|
| |
| }
| |
|
| |
| therm.read();
| |
| ambient_measurement = therm.ambient();
| |
| object_measurement = therm.object();
| |
| | |
| if ( last_ambient_measurement != ambient_measurement)
| |
| {
| |
| tft.setCursor(ambient_x_offset, ambient_y_offset + 8);
| |
| tft.println(String(therm.ambient(), 2));
| |
| }
| |
| | |
| if ( last_object_measurement != object_measurement)
| |
| {
| |
| tft.setCursor(object_x_offset, object_y_offset + 8);
| |
| tft.println(String(therm.object(), 2));
| |
| }
| |
| | |
| last_ambient_measurement = ambient_measurement;
| |
| last_object_measurement = object_measurement;
| |
| }
| |
| | |
| </nowiki>
| |
| | |
| ====AMG8833 Sensor (AMG_Stuff.h) ====
| |
| <nowiki>
| |
| //low range of the sensor (this will be blue on the screen)
| |
| #define MINTEMP 20
| |
| | |
| //high range of the sensor (this will be red on the screen)
| |
| #define MAXTEMP 28
| |
| | |
| //the colors we will be using
| |
| const uint16_t camColors[] = {0x480F,
| |
| 0x400F, 0x400F, 0x400F, 0x4010, 0x3810, 0x3810, 0x3810, 0x3810, 0x3010, 0x3010,
| |
| 0x3010, 0x2810, 0x2810, 0x2810, 0x2810, 0x2010, 0x2010, 0x2010, 0x1810, 0x1810,
| |
| 0x1811, 0x1811, 0x1011, 0x1011, 0x1011, 0x0811, 0x0811, 0x0811, 0x0011, 0x0011,
| |
| 0x0011, 0x0011, 0x0011, 0x0031, 0x0031, 0x0051, 0x0072, 0x0072, 0x0092, 0x00B2,
| |
| 0x00B2, 0x00D2, 0x00F2, 0x00F2, 0x0112, 0x0132, 0x0152, 0x0152, 0x0172, 0x0192,
| |
| 0x0192, 0x01B2, 0x01D2, 0x01F3, 0x01F3, 0x0213, 0x0233, 0x0253, 0x0253, 0x0273,
| |
| 0x0293, 0x02B3, 0x02D3, 0x02D3, 0x02F3, 0x0313, 0x0333, 0x0333, 0x0353, 0x0373,
| |
| 0x0394, 0x03B4, 0x03D4, 0x03D4, 0x03F4, 0x0414, 0x0434, 0x0454, 0x0474, 0x0474,
| |
| 0x0494, 0x04B4, 0x04D4, 0x04F4, 0x0514, 0x0534, 0x0534, 0x0554, 0x0554, 0x0574,
| |
| 0x0574, 0x0573, 0x0573, 0x0573, 0x0572, 0x0572, 0x0572, 0x0571, 0x0591, 0x0591,
| |
| 0x0590, 0x0590, 0x058F, 0x058F, 0x058F, 0x058E, 0x05AE, 0x05AE, 0x05AD, 0x05AD,
| |
| 0x05AD, 0x05AC, 0x05AC, 0x05AB, 0x05CB, 0x05CB, 0x05CA, 0x05CA, 0x05CA, 0x05C9,
| |
| 0x05C9, 0x05C8, 0x05E8, 0x05E8, 0x05E7, 0x05E7, 0x05E6, 0x05E6, 0x05E6, 0x05E5,
| |
| 0x05E5, 0x0604, 0x0604, 0x0604, 0x0603, 0x0603, 0x0602, 0x0602, 0x0601, 0x0621,
| |
| 0x0621, 0x0620, 0x0620, 0x0620, 0x0620, 0x0E20, 0x0E20, 0x0E40, 0x1640, 0x1640,
| |
| 0x1E40, 0x1E40, 0x2640, 0x2640, 0x2E40, 0x2E60, 0x3660, 0x3660, 0x3E60, 0x3E60,
| |
| 0x3E60, 0x4660, 0x4660, 0x4E60, 0x4E80, 0x5680, 0x5680, 0x5E80, 0x5E80, 0x6680,
| |
| 0x6680, 0x6E80, 0x6EA0, 0x76A0, 0x76A0, 0x7EA0, 0x7EA0, 0x86A0, 0x86A0, 0x8EA0,
| |
| 0x8EC0, 0x96C0, 0x96C0, 0x9EC0, 0x9EC0, 0xA6C0, 0xAEC0, 0xAEC0, 0xB6E0, 0xB6E0,
| |
| 0xBEE0, 0xBEE0, 0xC6E0, 0xC6E0, 0xCEE0, 0xCEE0, 0xD6E0, 0xD700, 0xDF00, 0xDEE0,
| |
| 0xDEC0, 0xDEA0, 0xDE80, 0xDE80, 0xE660, 0xE640, 0xE620, 0xE600, 0xE5E0, 0xE5C0,
| |
| 0xE5A0, 0xE580, 0xE560, 0xE540, 0xE520, 0xE500, 0xE4E0, 0xE4C0, 0xE4A0, 0xE480,
| |
| 0xE460, 0xEC40, 0xEC20, 0xEC00, 0xEBE0, 0xEBC0, 0xEBA0, 0xEB80, 0xEB60, 0xEB40,
| |
| 0xEB20, 0xEB00, 0xEAE0, 0xEAC0, 0xEAA0, 0xEA80, 0xEA60, 0xEA40, 0xF220, 0xF200,
| |
| 0xF1E0, 0xF1C0, 0xF1A0, 0xF180, 0xF160, 0xF140, 0xF100, 0xF0E0, 0xF0C0, 0xF0A0,
| |
| 0xF080, 0xF060, 0xF040, 0xF020, 0xF800,
| |
| };
| |
| | |
| Adafruit_AMG88xx amg;
| |
| unsigned long delayTime;
| |
| | |
| #define AMG_COLS 8
| |
| #define AMG_ROWS 8
| |
| float pixels[AMG_COLS * AMG_ROWS];
| |
| | |
| #define INTERPOLATED_COLS 24
| |
| #define INTERPOLATED_ROWS 24
| |
| | |
| | |
| float get_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
| |
| void set_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y, float f);
| |
| void get_adjacents_1d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
| |
| void get_adjacents_2d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
| |
| float cubicInterpolate(float p[], float x);
| |
| float bicubicInterpolate(float p[], float x, float y);
| |
| void interpolate_image(float *src, uint8_t src_rows, uint8_t src_cols,
| |
| float *dest, uint8_t dest_rows, uint8_t dest_cols);
| |
| | |
| void setup_AMG()
| |
| {
| |
| if (!amg.begin())
| |
| {
| |
| Serial.println("Could not find a valid AMG88xx sensor, check wiring!");
| |
| while (1) { delay(1); }
| |
| }
| |
| // Serial.println("-- Thermal Camera Test --");
| |
| }
| |
| | |
| void AMG_Reset()
| |
| {
| |
|
| |
| }
| |
| | |
| void drawpixels(int x_offset, int y_offset, float *p, uint8_t rows, uint8_t cols, uint8_t boxWidth, uint8_t boxHeight)
| |
| {
| |
| int colorTemp;
| |
| // int x_offset = 4, y_offset = 0;
| |
|
| |
| for (int y = 0; y < rows; y++)
| |
| {
| |
| for (int x = 0; x < cols; x++)
| |
| {
| |
| float val = get_point(p, rows, cols, x, y);
| |
| if (val >= MAXTEMP) colorTemp = MAXTEMP;
| |
| else if (val <= MINTEMP) colorTemp = MINTEMP;
| |
| else colorTemp = val;
| |
| | |
| uint8_t colorIndex = map(colorTemp, MINTEMP, MAXTEMP, 0, 255);
| |
| colorIndex = constrain(colorIndex, 0, 255);
| |
| //draw the pixels!
| |
| uint16_t color;
| |
| color = val * 2;
| |
| tft.fillRect(x_offset + (boxWidth * x), y_offset + (((rows-1) - y) * boxHeight), boxWidth, boxHeight, camColors[colorIndex]);
| |
| }
| |
| }
| |
| }
| |
| | |
| int AMG_x_offset = 44;
| |
| int AMG_y_offset = 0;
| |
| int AMG_x_width = 74;
| |
| int AMG_y_height = 74;
| |
| | |
| | |
| void AMG_Frame()
| |
| {
| |
| | |
| int AMG_box_top = AMG_y_offset;
| |
| int AMG_box_left = AMG_x_offset;
| |
| int AMG_box_bottom = AMG_box_top + AMG_y_height;
| |
| int AMG_box_right = AMG_box_left + AMG_x_width;
| |
| int AMG_box_width = AMG_x_width;
| |
| int AMG_box_height = AMG_y_height;
| |
| int AMG_frame_left = AMG_box_left + 1;
| |
| int AMG_frame_top = AMG_box_top + 1;
| |
|
| |
| int box_size = 3;
| |
|
| |
| //read all the pixels
| |
| amg.readPixels(pixels);
| |
| float dest_2d[INTERPOLATED_ROWS * INTERPOLATED_COLS];
| |
| int32_t t = millis();
| |
| interpolate_image(pixels, AMG_ROWS, AMG_COLS, dest_2d, INTERPOLATED_ROWS, INTERPOLATED_COLS);
| |
| // Serial.print("Interpolation took "); Serial.print(millis() - t); Serial.println(" ms");
| |
| // uint16_t boxsize = min(tft.width() / INTERPOLATED_COLS, tft.height() / INTERPOLATED_COLS);
| |
| tft.drawRect(AMG_box_left, AMG_box_top, AMG_box_width, AMG_box_height, ST7735_ORANGE);
| |
| drawpixels(AMG_frame_left,AMG_frame_top,dest_2d, INTERPOLATED_ROWS, INTERPOLATED_COLS, box_size, box_size);
| |
| }
| |
| | |
| </nowiki>
| |
| | |
| ==== BioAmp EXG (EXG_Stuff.h) ====
| |
| <nowiki>
| |
| #define EXG_SAMPLE_SIZE 155
| |
| #define EXG_PIN A0
| |
| | |
| int EXG_x_offset = 0;
| |
| int EXG_y_offset = 0;
| |
| int EXG_x_width = 128;
| |
| int EXG_y_height = 160;
| |
| | |
| void EXG_Frame()
| |
| {
| |
|
| |
| int box_top = EXG_y_offset;
| |
| int box_bottom = box_top + EXG_y_height;
| |
|
| |
| int box_left = EXG_x_offset;
| |
| int box_right = box_left + EXG_x_width;
| |
|
| |
| int box_width = EXG_x_width;
| |
| int box_height = EXG_y_height;
| |
| | |
| tft.fillRect(box_left, box_top, box_width, box_height, ST7735_WHITE);
| |
| tft.drawRect(box_left+1, box_top+1, box_width-3, box_height-3, ST7735_BLACK);
| |
|
| |
| }
| |
|
| |
|
| void EXG_Display_Data(int * EXG_data)
| | #include "HeartBeat_Stuff.h" |
| {
| | #include "ThermalImager_Stuff.h" |
| int box_top = EXG_y_offset;
| | #include "TOFLaser_Stuff.h" |
| int box_bottom = box_top + EXG_y_height;
| | #include "NonContactThermometer_Stuff.h" |
|
| | #include "FingerPrint_Stuff.h" |
| int box_left = EXG_x_offset;
| |
| int box_right = box_left + EXG_x_width;
| |
|
| |
| int box_width = EXG_x_width;
| |
| int box_height = EXG_y_height;
| |
|
| |
| int max_value = -5000;
| |
| int min_value = 5000;
| |
| int data_point1,data_point2;
| |
|
| |
| tft.fillRect(box_left+2, box_top+2, box_width-5, box_height-5, ST7735_WHITE);
| |
|
| |
| for(int x=0;x<EXG_SAMPLE_SIZE; ++x)
| |
| {
| |
| if (EXG_data[x] > max_value)
| |
| max_value = EXG_data[x];
| |
| if (EXG_data[x] < min_value)
| |
| min_value = EXG_data[x];
| |
| }
| |
| for(int x=0;x<EXG_SAMPLE_SIZE-1; ++x)
| |
| {
| |
| data_point1 = map(EXG_data[x],min_value,max_value,2,124);
| |
| data_point2 = map(EXG_data[x+1],min_value,max_value,2,124);
| |
| tft.drawLine(data_point1,x+2,data_point2,x+3,ST7735_RED);
| |
| Serial.println(data_point1);
| |
| }
| |
|
| |
| }
| |
| | |
| void EXG_Collect()
| |
| {
| |
| int EXG_Delay = 30;
| |
| int EXG_data[EXG_SAMPLE_SIZE];
| |
|
| |
| for(int x=0;x<EXG_SAMPLE_SIZE; ++x)
| |
| {
| |
| EXG_data[x] = analogRead(EXG_PIN);
| |
| delay(EXG_Delay);
| |
| }
| |
|
| |
|
| EXG_Display_Data(EXG_data);
| | #include "ControlPanel_Stuff.h" |
|
| | #include "AudioBoard_Stuff.h" |
| }
| |
|
| |
|
|
| |
| void EXG_Demo()
| |
| {
| |
| EXG_Frame();
| |
| while(1)
| |
| {
| |
| EXG_Collect();
| |
| }
| |
| }
| |
| </nowiki>
| |
|
| |
| ==== Core ====
| |
| <nowiki>
| |
| void setup() | | void setup() |
| { | | { |
| Wire.begin(); | | Wire.begin(); |
| | Wire1.begin(); |
| Serial.begin(115200); | | Serial.begin(115200); |
|
| |
|
| | analogReadResolution(12); |
| | |
| Serial.println("SETUP - Begin"); | | Serial.println("SETUP - Begin"); |
| Serial.println("TFT"); | | Serial.println("TFT"); |
| setup_TFT(); | | setup_TFT(); |
| | Serial.println("SD Card"); |
| | setup_SD(); |
| | |
| Serial.println("CT"); | | Serial.println("CT"); |
| setup_CT(); | | setup_NonContactThermometer(); |
| Serial.println("AMG"); | | Serial.println("ThermalImager"); |
| setup_AMG(); | | setup_ThermalImager(); |
| Serial.println("VL"); | | Serial.println("TOFLaser"); |
| setup_VL(); | | setup_TOFLaser(); |
| Serial.println("HB"); | | Serial.println("HeartBeat"); |
| setup_HB(); | | setup_HeartBeat(); |
| Serial.println("FP"); | | Serial.println("FingerPrint"); |
| setup_FP(); | | setup_FingerPrint(); |
| | Serial.println("ControlPanel"); |
| | setup_ControlPanel(); |
| | Serial.println("AudioBoard"); |
| | setup_AudioBoard(); |
| Serial.println("SETUP - End"); | | Serial.println("SETUP - End"); |
| } | | } |
| | |
|
| |
|
| void loop() | | void loop() |
| { | | { |
|
| | TOFLaser_Frame(); |
| VL_Frame();
| | ThermalImager_Frame(); |
| AMG_Frame();
| | NonContactThermometer_Frame(); |
| CT_Frame();
| | FingerPrint_Frame(); |
| FP_Frame();
| | HeartBeat_Frame(); |
| HB_Frame();
| | } |
|
| |
|
| if (EXG_Mode)
| |
| {
| |
| EXG_Frame();
| |
| while(EXG_Mode)
| |
| {
| |
| EXG_Collect();
| |
| VL_Reading();
| |
| }
| |
| TFT_Reset();
| |
| VL_Reset();
| |
| AMG_Reset();
| |
| CT_Reset();
| |
| FP_Reset();
| |
| HB_Reset();
| |
| }
| |
| }
| |
| </nowiki> | | </nowiki> |
|
| |
|
| [[Pseudo-Medical Monitor]] | | [[Pseudo-Medical Monitor]] |