Krishna VemuriVrishak Vemuri
Published © GPL3+

Community Safety Protector

This uses AMG8833 and HC-SR04 to measure temperature and give an output to Alexa, AWS DynamoDB, 1.44" TFT and LCD with a NodeMcu.

AdvancedFull instructions provided15 hours5,709
Community Safety Protector

Things used in this project

Hardware components

Arduino Mega 2560
Arduino Mega 2560
×1
Nodemcu v1.0 ESP8266
×1
Solderless Breadboard Full Size
Solderless Breadboard Full Size
×2
Adafruit AMG8833 IR Thermal Camera Breakout
×1
Adafruit 1.44" Color TFT LCD Display with MicroSD Card breakout - ST7735R
×1
Ultrasonic Sensor - HC-SR04 (Generic)
Ultrasonic Sensor - HC-SR04 (Generic)
×1
Standard LCD - 16x2 White on Blue
Adafruit Standard LCD - 16x2 White on Blue
Any 16 pin LCD is OK.
×1
Trimmer Potentiometer, 10 kohm
Trimmer Potentiometer, 10 kohm
×1
Resistor 220 ohm
Resistor 220 ohm
×1
micro SD card
Any Micro SD card is OK, as long it is 32GB or less.
×1
USB-A to B Cable
USB-A to B Cable
×1
USB-A to Micro-USB Cable
USB-A to Micro-USB Cable
×1
Jumper wires (generic)
Jumper wires (generic)
You need 37 wires.
×37

Software apps and online services

Arduino IDE
Arduino IDE
Alexa Skills Kit
Amazon Alexa Alexa Skills Kit
AWS DynamoDB
Amazon Web Services AWS DynamoDB
AWS Lambda
Amazon Web Services AWS Lambda
AWS IoT
Amazon Web Services AWS IoT
Visual Studio 2017
Microsoft Visual Studio 2017

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Any solder iron and solder is good; this is just to solder the AMG8833 and TFT pins.
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Schematics

Diagram of Arduino Piece

How to wire the Arduino connections--Fritzing Diagram

Schematic of Arduino Piece

How to wire the Arduino Connections--Schematic

Code

ArduinoFinalCode

C/C++
This is the code to be compiled for Arduino MEGA 2560 using arduino IDE.
/*This is a project by Vrishak and Krishna Vemuri. This takes the temperature from the AMG8833 sensor and distance from HC-SR04. This corrects the temperature with the distance. Then, the pixels are shown on the SD card. The temperature is reported to NodeMcu, LCD, and SD card  
**************************************************************************
  This is a library for the AMG88xx GridEYE 8x8 IR camera

  This sketch makes a 64 pixel thermal camera with the GridEYE sensor
  and a 128x128 tft screen https://www.adafruit.com/product/2088

  Designed specifically to work with the Adafruit AMG88 breakout
  ----> http://www.adafruit.com/products/3538

  These sensors use I2C to communicate. The device's I2C address is 0x69

  Adafruit invests time and resources providing this open source code,
  please support Adafruit andopen-source hardware by purchasing products
  from Adafruit!

  Written by Dean Miller for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ***************************************************************************/

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>

#include <Wire.h>
#include <Adafruit_AMG88xx.h>
#include <SR04.h>
#include <LiquidCrystal.h>
#include <SD.h>
#define TFT_CS     53 //chip select pin for the TFT screen
#define TFT_RST    9  // you can also connect this to the Arduino reset
                      // in which case, set this #define pin to 0!
#define TFT_DC     8

//low range of the sensor (this will be blue on the screen)
#define MINTEMP 22

//high range of the sensor (this will be red on the screen)
#define MAXTEMP 34
#define trig 12
#define echo 11
SR04 sr04 = SR04(echo,trig);
LiquidCrystal lcd(27, 28, 29, 30, 31, 32);
File file;
int cardpin = 4; 
long dist;
//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_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);

Adafruit_AMG88xx amg;
unsigned long delayTime;
float pixels[AMG88xx_PIXEL_ARRAY_SIZE];
uint16_t displayPixelWidth, displayPixelHeight;

void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);
    Serial.println(F("AMG88xx thermal camera!"));

    tft.initR(INITR_144GREENTAB);   // initialize a ST7735S chip, black tab
    tft.fillScreen(ST7735_BLACK);

    displayPixelWidth = tft.width() / 8;
    displayPixelHeight = tft.height() / 8;

    //tft.setRotation(3);
    
    bool status;
    
    // default settings
    status = amg.begin();
    if (!status) {
        Serial.println("Could not find a valid AMG88xx sensor, check wiring!");
        while (1);
    }
    
    Serial.println("-- Thermal Camera Test --");
    lcd.begin(16, 2);
    delay(100); // let sensor boot up
    pinMode(cardpin, OUTPUT); 
    if (!SD.begin(cardpin)) { 
      Serial.println("SD card initialization failed");
    }
  
    if (SD.exists("data.txt")) {
      Serial.println("data.txt exists.");
      if (SD.remove("data.txt")) {
        Serial.println("Successfully removed file.");
      } else {
        Serial.println("Could not remove data file.");
      }
    }
    

}  

void loop() {
  //read all the pixels
  amg.readPixels(pixels);
  float maxx = -99.9;
  for(int i=0; i<AMG88xx_PIXEL_ARRAY_SIZE; i++){
    uint8_t colorIndex = map(pixels[i], MINTEMP, MAXTEMP, 0, 255);
    colorIndex = constrain(colorIndex, 0, 255);

    //draw the pixels!
    tft.fillRect(displayPixelHeight * floor(i / 8), displayPixelWidth * (i % 8),
        displayPixelHeight, displayPixelWidth, camColors[colorIndex]);
    if(pixels[i]>maxx){
      maxx = pixels[i];
    }
  }
  dist=sr04.Distance();
  if(dist>40){
    Serial.println("Come closer");
    lcd.print("Come closer");
  }
  else{
    if(dist<6){
      Serial.println("Go farther");
      lcd.print("Go farther");
    }
    else{
      Serial.print(dist);
      Serial.println(" cm");
      float newmax = round((maxx+5.25+(dist/9))*100);
      float new2 = newmax/100;
      float degreesF = (1.8*new2+32)*100;
      int intF = (int) degreesF;
      Serial.println(degreesF);
      Serial.println(intF);
      
      lcd.setCursor(0, 0);
      lcd.print("Temp: "+String(degreesF/100));
      Serial1.println(intF);
      lcd.setCursor(0,1);
      //Degrees F is the degree measure without the decimal point.
      if(degreesF < 10040){
        lcd.print("Person is safe");
        
      }
      else{
        if(degreesF <= 10220){
          lcd.print("Send person home");
          
        }
        else{
          lcd.print("Person go to ER");
          
        }
      }
      file = SD.open("data.txt", FILE_WRITE);
      if (file) {
        String fulldata = "Temp: "+String(degreesF);
        file.println(fulldata);
        file.close();
      }
      else {
        Serial.println("Error in writing data file");
        
      }
      
      
      
      
    
      
    }
  }
  delay(200);
  lcd.clear();
  
}

NodeMcuFinalCode

C/C++
This is the code to be uploaded onto the NodeMcu v1.0 via Arduino IDE
#include "FS.h"
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

// Update these with values suitable for your network.

const char* ssid = "X5TM9";
const char* password = "4444444444*";

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");

const char* AWS_endpoint = "a11hkjq6oj6lfh-ats.iot.us-east-1.amazonaws.com"; //MQTT broker ip

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

}
WiFiClientSecure espClient;
PubSubClient client(AWS_endpoint, 8883, callback, espClient); //set MQTT port number to 8883 as per //standard
//==========================================================================
#define BUFFER_LEN 256
long lastMsg = 0;
char msg[BUFFER_LEN];
int value = 0;
byte mac[6];
char mac_Id[18];
//===========================================================================

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  espClient.setBufferSizes(512, 512);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  timeClient.begin();
  while (!timeClient.update()) {
    timeClient.forceUpdate();
  }

  espClient.setX509Time(timeClient.getEpochTime());

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESPthing")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic", "degreesF");
      // ... and resubscribe
      client.subscribe("inTopic");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");

      char buf[256];
      espClient.getLastSSLError(buf, 256);
      Serial.print("WiFiClientSecure SSL error: ");
      Serial.println(buf);

      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {

  Serial.begin(9600);
  while (!Serial) {
    ;
  }
  Serial.setDebugOutput(true);
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  setup_wifi();
  delay(1000);
  if (!SPIFFS.begin()) {
    Serial.println("Failed to mount file system");
    return;
  }

  Serial.print("Heap: "); Serial.println(ESP.getFreeHeap());

  // Load certificate file
  File cert = SPIFFS.open("/cert.der", "r"); //replace cert.crt eith your uploaded file name
  if (!cert) {
    Serial.println("Failed to open cert file");
  }
  else
    Serial.println("Success to open cert file");

  delay(1000);

  if (espClient.loadCertificate(cert))
    Serial.println("cert loaded");
  else
    Serial.println("cert not loaded");

  // Load private key file
  File private_key = SPIFFS.open("/private.der", "r"); //replace private eith your uploaded file name
  if (!private_key) {
    Serial.println("Failed to open private cert file");
  }
  else
    Serial.println("Success to open private cert file");

  delay(1000);

  if (espClient.loadPrivateKey(private_key))
    Serial.println("private key loaded");
  else
    Serial.println("private key not loaded");

  // Load CA file
  File ca = SPIFFS.open("/ca.der", "r"); //replace ca eith your uploaded file name
  if (!ca) {
    Serial.println("Failed to open ca ");
  }
  else
    Serial.println("Success to open ca");

  delay(1000);

  if (espClient.loadCACert(ca))
    Serial.println("ca loaded");
  else
    Serial.println("ca failed");

  Serial.print("Heap: "); Serial.println(ESP.getFreeHeap());
  //==========================================================================
  WiFi.macAddress(mac);
  snprintf(mac_Id, sizeof(mac_Id), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  Serial.print(mac_Id);
  //============================================================================
}
int isnull = 0;
String data = "";
int incomingByte = 13; //carrige return
void loop() {

  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  if (Serial.available() > 0) {
    // read the incoming byte:
    int incomingByte = Serial.read();
    if (incomingByte != 10 && incomingByte != 13) { //10 is new line, 13 is carrige return.

      incomingByte -= 48;
      data += String(incomingByte);
    }
    else {
      if (incomingByte != 13) {
        // do macIDSTR and upload to DB
        Serial.println("Data full is (without decimal point) " + data);
        int dataasint = data.toInt();
        float datafloat = (float) dataasint / 100;
        if (datafloat >= 100.4) { //38 degrees C
          data = String(datafloat);
          Serial.println(data);
          String macIdStr = mac_Id;
          snprintf (msg, BUFFER_LEN, "{\"mac_Id\" : \"%s\", \"degrees_f\" : \"%s\"}", macIdStr.c_str(), data.c_str());
          Serial.print("Publish message: ");
          digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
          Serial.println(msg);
          //mqttClient.publish("outTopic", msg);
          client.publish("outTopic", msg);
          //=========================================================================
          Serial.print("Heap: ");
          Serial.println(ESP.getFreeHeap()); //Low heap can cause problems
        }

        data = "";




      }
    }

   
  }
}

handler.js

JSON
Lambda function to bind Alexa skill.
'use strict';
const AWS = require('aws-sdk');
const Alexa = require("alexa-sdk");
const lambda = new AWS.Lambda();
const dynamoDb = new AWS.DynamoDB.DocumentClient();
exports.handler = function (event, context, callback) {
  const alexa = Alexa.handler(event, context);
  alexa.appId = "amzn1.ask.skill.XXXXXXXXXXXXXXXXXXX";
  alexa.registerHandlers(handlers);
  alexa.execute();
};
const handlers = {
  'LaunchRequest': function () {
    this.emit('Prompt');
  },
  'Unhandled': function () {
    this.emit('AMAZON.HelpIntent');
  },
  
  'GetTotal': function () {
    var srchDate = this.event.request.intent.slots.thisDate.value;
    var theDate01 = Date.parse(srchDate);
    var theDate02 = theDate01+86400000;
    var itemCount = 1200;

    const params = {
      TableName:'TABLE_NAME',
      FilterExpression: 'createdAt >= :startDT AND createdAt <= :endDT',
      ExpressionAttributeValues: {
        ':startDT': theDate01,
        ':endDT': theDate02
      }
    };
    console.log('Getting the count'+theDate01+' and '+theDate02,params);
    const self = this;
    dynamoDb.scan(params, function (err, data) {
      itemCount = data.Count;
      if(itemCount>0)
      {
        console.log('Total Items'+itemCount);
        self.emit(':ask', 'On '+srchDate+', there were '+itemCount+' cases of high temperature');  
      }
      else
      {
        self.emit(':ask', 'On '+srchDate+', there were no cases of high temperature');
      }
    });
  },
  'AMAZON.YesIntent': function () {
    this.emit('Prompt');
  },
  'AMAZON.NoIntent': function () {
    this.emit('AMAZON.StopIntent');
  },
  'Prompt': function () {
    this.emit(':ask', 'Welcome to community safety protector alexa Q and A. You can ask how many cases there were on a specific day and safety precautions to take with the number of cases.');
  },
  'NoMatch': function () {
    this.emit(':ask', 'Sorry, I couldn\'t understand.', 'Please say that again?');
  },
  'AMAZON.HelpIntent': function () {
    const speechOutput = 'You can ask the number of scans and also ask for safety precautions';
    const reprompt = 'Say Alexa to hear me back';
    this.response.speak(speechOutput).listen(reprompt);
    this.emit(':responseReady');
  },
  'AMAZON.CancelIntent': function () {
    this.response.speak('Goodbye!');
    this.emit(':responseReady');
  },
  'AMAZON.StopIntent': function () {
    this.response.speak('See you later!');
    this.emit(':responseReady');
  }
};

serverless.yml

YAML
YAML file created using serverless with necessary code for this project
service: XXXXXXXXXXXXXXXXX

provider:
  name: aws
  runtime: nodejs12.x
  region: us-east-1
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource: "arn:aws:dynamodb:us-east-1:XXXXXXXXXXXXXX"

custom:
  defaultStage: dev
  profiles:
    dev: serverless
    prod: serverless
  dynamodb:
      start:
        migrate: true

functions:
  GetTotal:
    handler:  handler.handler
    events:
      - alexaSkill

Alexa Skill

JSON
Alexa skill with Invocation, Intents and Utterance
{
    "interactionModel": {
        "languageModel": {
            "invocationName": "community safety protector",
            "intents": [
                {
                    "name": "AMAZON.StartOverIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.RepeatIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": [
                        "help",
                        "help me"
                    ]
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": [
                        "stop"
                    ]
                },
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": [
                        "cancel"
                    ]
                },
                {
                    "name": "AMAZON.YesIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.NoIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.NavigateHomeIntent",
                    "samples": []
                },
                {
                    "name": "GetTotal",
                    "slots": [
                        {
                            "name": "thisDate",
                            "type": "AMAZON.DATE"
                        }
                    ],
                    "samples": [
                        "count for {thisDate}",
                        "what is the count of {thisDate}",
                        "Get the total for this {thisDate}"
                    ]
                }
            ],
            "types": []
        }
    }
}

Credits

Krishna Vemuri

Krishna Vemuri

3 projects • 2 followers
Vrishak Vemuri

Vrishak Vemuri

3 projects • 3 followers
Your avid electronics enthusiast =D // Making magic blue smoke since summer 2018 // Currently in high school (class of 2025)

Comments