Erste Versuche mit wärmebildkamera,
2 ultraschallsensoren an einen esp angeschlossen
This commit is contained in:
parent
4441a65bfc
commit
944d0a19b1
312
arduino/Arduino_ESP32_MLX90640/Arduino_ESP32_MLX90640.ino
Normal file
312
arduino/Arduino_ESP32_MLX90640/Arduino_ESP32_MLX90640.ino
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
#include <Wire.h>
|
||||||
|
#include "MLX90640_API.h"
|
||||||
|
#include "MLX90640_I2C_Driver.h"
|
||||||
|
//#include "SPI.h"
|
||||||
|
//#include "Adafruit_GFX.h"
|
||||||
|
//#include "Adafruit_ILI9341.h"
|
||||||
|
|
||||||
|
// For the ESP-WROVER_KIT, these are the default.
|
||||||
|
/*#define TFT_CS 15
|
||||||
|
#define TFT_DC 2
|
||||||
|
#define TFT_MOSI 13
|
||||||
|
#define TFT_CLK 14
|
||||||
|
#define TFT_RST 26
|
||||||
|
#define TFT_MISO 12
|
||||||
|
#define TFT_LED 27*/
|
||||||
|
|
||||||
|
/*Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);*/
|
||||||
|
|
||||||
|
const byte MLX90640_address = 0x33; //Default 7-bit unshifted address of the MLX90640
|
||||||
|
|
||||||
|
#define TA_SHIFT 8 //Default shift for MLX90640 in open air
|
||||||
|
|
||||||
|
static float mlx90640To[768];
|
||||||
|
paramsMLX90640 mlx90640;
|
||||||
|
|
||||||
|
int xPos, yPos; // Abtastposition
|
||||||
|
int R_colour, G_colour, B_colour; // RGB-Farbwert
|
||||||
|
int i, j; // Zählvariable
|
||||||
|
float T_max, T_min; // maximale bzw. minimale gemessene Temperatur
|
||||||
|
float T_center; // Temperatur in der Bildschirmmitte
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ***************************************
|
||||||
|
// **************** SETUP ****************
|
||||||
|
// ***************************************
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
Wire.begin();
|
||||||
|
Wire.setClock(400000); //Increase I2C clock speed to 400kHz
|
||||||
|
|
||||||
|
while (!Serial); //Wait for user to open terminal
|
||||||
|
|
||||||
|
Serial.println("MLX90640 IR Array Example");
|
||||||
|
|
||||||
|
if (isConnected() == false)
|
||||||
|
{
|
||||||
|
Serial.println("MLX90640 not detected at default I2C address. Please check wiring. Freezing.");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("MLX90640 online!");
|
||||||
|
|
||||||
|
//Get device parameters - We only have to do this once
|
||||||
|
int status;
|
||||||
|
uint16_t eeMLX90640[832];
|
||||||
|
|
||||||
|
status = MLX90640_DumpEE(MLX90640_address, eeMLX90640);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
Serial.println("Failed to load system parameters");
|
||||||
|
|
||||||
|
status = MLX90640_ExtractParameters(eeMLX90640, &mlx90640);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
{
|
||||||
|
Serial.println("Parameter extraction failed");
|
||||||
|
Serial.print(" status = ");
|
||||||
|
Serial.println(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Once params are extracted, we can release eeMLX90640 array
|
||||||
|
|
||||||
|
MLX90640_I2CWrite(0x33, 0x800D, 6401); // writes the value 1901 (HEX) = 6401 (DEC) in the register at position 0x800D to enable reading out the temperatures!!!
|
||||||
|
// ===============================================================================================================================================================
|
||||||
|
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x00); //Set rate to 0.25Hz effective - Works
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x01); //Set rate to 0.5Hz effective - Works
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x02); //Set rate to 1Hz effective - Works
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x03); //Set rate to 2Hz effective - Works
|
||||||
|
MLX90640_SetRefreshRate(MLX90640_address, 0x04); //Set rate to 4Hz effective - Works
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x05); //Set rate to 8Hz effective - Works at 800kHz
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x06); //Set rate to 16Hz effective - Works at 800kHz
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x07); //Set rate to 32Hz effective - fails
|
||||||
|
|
||||||
|
|
||||||
|
//pinMode(TFT_LED, OUTPUT);
|
||||||
|
//digitalWrite(TFT_LED, HIGH);
|
||||||
|
|
||||||
|
/*tft.begin();
|
||||||
|
|
||||||
|
tft.setRotation(1);
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
tft.fillRect(0, 0, 319, 13, tft.color565(255, 0, 10));
|
||||||
|
tft.setCursor(100, 3);
|
||||||
|
tft.setTextSize(1);
|
||||||
|
tft.setTextColor(ILI9341_YELLOW, tft.color565(255, 0, 10));
|
||||||
|
tft.print("Thermographie - stoppi");
|
||||||
|
|
||||||
|
tft.drawLine(250, 210 - 0, 258, 210 - 0, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(250, 210 - 30, 258, 210 - 30, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(250, 210 - 60, 258, 210 - 60, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(250, 210 - 90, 258, 210 - 90, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(250, 210 - 120, 258, 210 - 120, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(250, 210 - 150, 258, 210 - 150, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(250, 210 - 180, 258, 210 - 180, tft.color565(255, 255, 255));
|
||||||
|
|
||||||
|
tft.setCursor(80, 220);
|
||||||
|
tft.setTextColor(ILI9341_WHITE, tft.color565(0, 0, 0));
|
||||||
|
tft.print("T+ = ");
|
||||||
|
|
||||||
|
|
||||||
|
// drawing the colour-scale
|
||||||
|
// ========================
|
||||||
|
|
||||||
|
for (i = 0; i < 181; i++)
|
||||||
|
{
|
||||||
|
//value = random(180);
|
||||||
|
|
||||||
|
getColour(i);
|
||||||
|
tft.drawLine(240, 210 - i, 250, 210 - i, tft.color565(R_colour, G_colour, B_colour));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// **********************************
|
||||||
|
// ************** LOOP **************
|
||||||
|
// **********************************
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
for (byte x = 0 ; x < 2 ; x++) //Read both subpages
|
||||||
|
{
|
||||||
|
uint16_t mlx90640Frame[834];
|
||||||
|
int status = MLX90640_GetFrameData(MLX90640_address, mlx90640Frame);
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
{
|
||||||
|
Serial.print("GetFrame Error: ");
|
||||||
|
Serial.println(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
float vdd = MLX90640_GetVdd(mlx90640Frame, &mlx90640);
|
||||||
|
float Ta = MLX90640_GetTa(mlx90640Frame, &mlx90640);
|
||||||
|
|
||||||
|
float tr = Ta - TA_SHIFT; //Reflected temperature based on the sensor ambient temperature
|
||||||
|
float emissivity = 0.95;
|
||||||
|
|
||||||
|
MLX90640_CalculateTo(mlx90640Frame, &mlx90640, emissivity, tr, mlx90640To);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// determine T_min and T_max and eliminate error pixels
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
mlx90640To[1*32 + 21] = 0.5 * (mlx90640To[1*32 + 20] + mlx90640To[1*32 + 22]); // eliminate the error-pixels
|
||||||
|
mlx90640To[4*32 + 30] = 0.5 * (mlx90640To[4*32 + 29] + mlx90640To[4*32 + 31]); // eliminate the error-pixels
|
||||||
|
|
||||||
|
T_min = mlx90640To[0];
|
||||||
|
T_max = mlx90640To[0];
|
||||||
|
|
||||||
|
for (i = 1; i < 768; i++)
|
||||||
|
{
|
||||||
|
if((mlx90640To[i] > -41) && (mlx90640To[i] < 301))
|
||||||
|
{
|
||||||
|
if(mlx90640To[i] < T_min)
|
||||||
|
{
|
||||||
|
T_min = mlx90640To[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mlx90640To[i] > T_max)
|
||||||
|
{
|
||||||
|
T_max = mlx90640To[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(i > 0) // temperature out of range
|
||||||
|
{
|
||||||
|
mlx90640To[i] = mlx90640To[i-1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mlx90640To[i] = mlx90640To[i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// determine T_center
|
||||||
|
// ==================
|
||||||
|
|
||||||
|
T_center = mlx90640To[11* 32 + 15];
|
||||||
|
|
||||||
|
// drawing the picture
|
||||||
|
// ===================
|
||||||
|
|
||||||
|
for (i = 0 ; i < 24 ; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 32; j++)
|
||||||
|
{
|
||||||
|
mlx90640To[i*32 + j] = 180.0 * (mlx90640To[i*32 + j] - T_min) / (T_max - T_min);
|
||||||
|
|
||||||
|
getColour(mlx90640To[i*32 + j]);
|
||||||
|
|
||||||
|
// tft.fillRect(217 - j * 7, 35 + i * 7, 7, 7, tft.color565(R_colour, G_colour, B_colour));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
tft.drawLine(217 - 15*7 + 3.5 - 5, 11*7 + 35 + 3.5, 217 - 15*7 + 3.5 + 5, 11*7 + 35 + 3.5, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(217 - 15*7 + 3.5, 11*7 + 35 + 3.5 - 5, 217 - 15*7 + 3.5, 11*7 + 35 + 3.5 + 5, tft.color565(255, 255, 255));
|
||||||
|
|
||||||
|
tft.fillRect(260, 25, 37, 10, tft.color565(0, 0, 0));
|
||||||
|
tft.fillRect(260, 205, 37, 10, tft.color565(0, 0, 0));
|
||||||
|
tft.fillRect(115, 220, 37, 10, tft.color565(0, 0, 0));
|
||||||
|
|
||||||
|
tft.setTextColor(ILI9341_WHITE, tft.color565(0, 0, 0));
|
||||||
|
tft.setCursor(265, 25);
|
||||||
|
tft.print(T_max, 1);
|
||||||
|
tft.setCursor(265, 205);
|
||||||
|
tft.print(T_min, 1);
|
||||||
|
tft.setCursor(120, 220);
|
||||||
|
tft.print(T_center, 1);
|
||||||
|
|
||||||
|
tft.setCursor(300, 25);
|
||||||
|
tft.print("C");
|
||||||
|
tft.setCursor(300, 205);
|
||||||
|
tft.print("C");
|
||||||
|
tft.setCursor(155, 220);
|
||||||
|
tft.print("C");
|
||||||
|
*/
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ===============================
|
||||||
|
// ===== determine the colour ====
|
||||||
|
// ===============================
|
||||||
|
|
||||||
|
void getColour(int j)
|
||||||
|
{
|
||||||
|
if (j >= 0 && j < 30)
|
||||||
|
{
|
||||||
|
R_colour = 0;
|
||||||
|
G_colour = 0;
|
||||||
|
B_colour = 20 + (120.0/30.0) * j;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j >= 30 && j < 60)
|
||||||
|
{
|
||||||
|
R_colour = (120.0 / 30) * (j - 30.0);
|
||||||
|
G_colour = 0;
|
||||||
|
B_colour = 140 - (60.0/30.0) * (j - 30.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j >= 60 && j < 90)
|
||||||
|
{
|
||||||
|
R_colour = 120 + (135.0/30.0) * (j - 60.0);
|
||||||
|
G_colour = 0;
|
||||||
|
B_colour = 80 - (70.0/30.0) * (j - 60.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j >= 90 && j < 120)
|
||||||
|
{
|
||||||
|
R_colour = 255;
|
||||||
|
G_colour = 0 + (60.0/30.0) * (j - 90.0);
|
||||||
|
B_colour = 10 - (10.0/30.0) * (j - 90.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j >= 120 && j < 150)
|
||||||
|
{
|
||||||
|
R_colour = 255;
|
||||||
|
G_colour = 60 + (175.0/30.0) * (j - 120.0);
|
||||||
|
B_colour = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j >= 150 && j <= 180)
|
||||||
|
{
|
||||||
|
R_colour = 255;
|
||||||
|
G_colour = 235 + (20.0/30.0) * (j - 150.0);
|
||||||
|
B_colour = 0 + 255.0/30.0 * (j - 150.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Returns true if the MLX90640 is detected on the I2C bus
|
||||||
|
boolean isConnected()
|
||||||
|
{
|
||||||
|
Wire.beginTransmission((uint8_t)MLX90640_address);
|
||||||
|
|
||||||
|
if (Wire.endTransmission() != 0)
|
||||||
|
return (false); //Sensor did not ACK
|
||||||
|
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
#include "SR04.h"
|
#include "SR04.h"
|
||||||
#define TRIG_PIN 3
|
#define TRIG_PIN D3
|
||||||
#define ECHO_PIN 4
|
#define ECHO_PIN D4
|
||||||
SR04 sr04 = SR04(ECHO_PIN,TRIG_PIN);
|
SR04 sr04 = SR04(ECHO_PIN,TRIG_PIN);
|
||||||
long a;
|
long a;
|
||||||
|
|
||||||
|
@ -0,0 +1,157 @@
|
|||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
|
||||||
|
//Eigene zu trackende Entfernung festlegen
|
||||||
|
#define DISTANCE 155
|
||||||
|
|
||||||
|
const char* SSID = "smartroom";
|
||||||
|
const char* PSK = "smarthome";
|
||||||
|
const char* MQTT_BROKER = "192.168.252.1";
|
||||||
|
WiFiClient espClient;
|
||||||
|
PubSubClient client(espClient);
|
||||||
|
|
||||||
|
// defines pins numbers
|
||||||
|
const int trigPin = D3; //D4
|
||||||
|
const int echoPin1 = D4; //D3
|
||||||
|
const int echoPin2 = D2; //D2
|
||||||
|
|
||||||
|
long duration1;
|
||||||
|
long duration2;
|
||||||
|
int distance1;
|
||||||
|
int distance2;
|
||||||
|
int bool1 = 0;
|
||||||
|
int bool2 = 0;
|
||||||
|
char msg[50];
|
||||||
|
int value = 0;
|
||||||
|
long lastMsg = 0;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
|
||||||
|
pinMode(echoPin1, INPUT); // Sets the echoPin as an Input
|
||||||
|
pinMode(echoPin2, INPUT); // Sets the echoPin as an Input
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
setup_wifi();
|
||||||
|
client.setServer(MQTT_BROKER, 1883);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_wifi() {
|
||||||
|
delay(10);
|
||||||
|
Serial.println();
|
||||||
|
Serial.print("Connecting to ");
|
||||||
|
Serial.println(SSID);
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(SSID, PSK);
|
||||||
|
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
delay(500);
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("");
|
||||||
|
Serial.println("WiFi connected");
|
||||||
|
Serial.println("IP address: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
}
|
||||||
|
|
||||||
|
void reconnect() {
|
||||||
|
while (!client.connected()) {
|
||||||
|
Serial.print("Reconnecting...");
|
||||||
|
if (!client.connect("ESP8266Client")) {
|
||||||
|
Serial.print("failed, rc=");
|
||||||
|
Serial.print(client.state());
|
||||||
|
Serial.println(" retrying in 5 seconds");
|
||||||
|
delay(5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
if (!client.connected()) {
|
||||||
|
reconnect();
|
||||||
|
}
|
||||||
|
client.loop();
|
||||||
|
|
||||||
|
// Clears the trigPin
|
||||||
|
digitalWrite(trigPin, LOW);
|
||||||
|
delayMicroseconds(2);
|
||||||
|
|
||||||
|
// Sets the trigPin on HIGH state for 10 micro seconds
|
||||||
|
digitalWrite(trigPin, HIGH);
|
||||||
|
delayMicroseconds(10);
|
||||||
|
digitalWrite(trigPin, LOW);
|
||||||
|
|
||||||
|
// Reads the echoPin, returns the sound wave travel time in microseconds
|
||||||
|
duration1 = pulseIn(echoPin1, HIGH);
|
||||||
|
duration2 = pulseIn(echoPin2, HIGH);
|
||||||
|
|
||||||
|
// Calculating the distance
|
||||||
|
distance1 = getDistance(duration1);
|
||||||
|
distance2 = getDistance(duration2);
|
||||||
|
// Prints the distance1 on the Serial Monitor
|
||||||
|
/* if ((distance1!= (distance_alt - 1)) && (distance1!= (distance_alt)) && (distance1!= (distance_alt + 1))) { //+-1 um störungen herauszufiltern
|
||||||
|
snprintf (msg, 50, "%d", distance);
|
||||||
|
Serial.print("Publish Motion: ");
|
||||||
|
Serial.println(msg);
|
||||||
|
client.publish("/home/data", msg);
|
||||||
|
delay(200);
|
||||||
|
} */
|
||||||
|
bool1 = presenceDetection(bool1, distance1);
|
||||||
|
bool2 = presenceDetection(bool2, distance2);
|
||||||
|
|
||||||
|
delay(80);
|
||||||
|
}
|
||||||
|
|
||||||
|
int presenceDetection(int bool1, int distance1){
|
||||||
|
|
||||||
|
if (bool1 == 0) {
|
||||||
|
//alternativ: if ((distance1!= (DISTANCE - 1)) && (distance1!= (DISTANCE)) && (distance1!= (DISTANCE + 1))) { //+-1
|
||||||
|
|
||||||
|
if (((distance1 > (DISTANCE + 2)) || (distance1 < (DISTANCE - 2))) && (distance1 < (DISTANCE + 2))) { //darf +- 2 um festgelegte entfernung schwanken, um störungen herauszufiltern
|
||||||
|
//Meldung an PI, dass die Distanz gestört ist
|
||||||
|
snprintf (msg, 50, "%d", 1);
|
||||||
|
client.publish("/gso/bb/104/ultraschall/1", msg);
|
||||||
|
//Serieller Monitor
|
||||||
|
Serial.print("Motion detected! Distance: ");
|
||||||
|
Serial.println(distance1);
|
||||||
|
|
||||||
|
//Flag auf 1
|
||||||
|
bool1 = 1;
|
||||||
|
return bool1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
snprintf (msg, 50, "%d", 0);
|
||||||
|
client.publish("/gso/bb/104/ultraschall/1", msg);
|
||||||
|
return bool1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (bool1 == 1) {
|
||||||
|
if (((distance1> (DISTANCE + 2)) || (distance1<(DISTANCE - 2)))&&(distance1<(DISTANCE + 2))) { //darf +- 2 um festgelegte entfernung schwanken, um störungen herauszufiltern
|
||||||
|
Serial.print("Still motion detected! Distance: ");
|
||||||
|
Serial.println(distance1);
|
||||||
|
//Meldung an PI, dass die Ausgangsdistanz wieder gemessen wird
|
||||||
|
snprintf (msg, 50, "%d", 1);
|
||||||
|
client.publish("/gso/bb/104/ultraschall/1", msg);
|
||||||
|
|
||||||
|
return bool1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//Meldung an PI, dass die Ausgangsdistanz wieder gemessen wird
|
||||||
|
snprintf (msg, 50, "%d", 0);
|
||||||
|
client.publish("/gso/bb/104/ultraschall/1", msg);
|
||||||
|
|
||||||
|
//Flag wieder auf 0
|
||||||
|
bool1 = 0;
|
||||||
|
return bool1;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int getDistance(int duration){
|
||||||
|
int distance = duration * 0.034 / 2;
|
||||||
|
return distance;
|
||||||
|
}
|
@ -11,19 +11,23 @@ WiFiClient espClient;
|
|||||||
PubSubClient client(espClient);
|
PubSubClient client(espClient);
|
||||||
|
|
||||||
// defines pins numbers
|
// defines pins numbers
|
||||||
const int trigPin = 2; //D4
|
const int trigPin = D3; //D4
|
||||||
const int echoPin = 0; //D3
|
const int echoPin1 = D4; //D3
|
||||||
|
|
||||||
|
long duration1;
|
||||||
|
|
||||||
|
int distance1;
|
||||||
|
|
||||||
long duration;
|
|
||||||
int distance;
|
|
||||||
int bool1 = 0;
|
int bool1 = 0;
|
||||||
|
|
||||||
char msg[50];
|
char msg[50];
|
||||||
int value = 0;
|
int value = 0;
|
||||||
long lastMsg = 0;
|
long lastMsg = 0;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
|
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
|
||||||
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
|
pinMode(echoPin1, INPUT); // Sets the echoPin as an Input
|
||||||
|
|
||||||
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
setup_wifi();
|
setup_wifi();
|
||||||
@ -79,45 +83,59 @@ void loop() {
|
|||||||
digitalWrite(trigPin, LOW);
|
digitalWrite(trigPin, LOW);
|
||||||
|
|
||||||
// Reads the echoPin, returns the sound wave travel time in microseconds
|
// Reads the echoPin, returns the sound wave travel time in microseconds
|
||||||
duration = pulseIn(echoPin, HIGH);
|
duration1 = pulseIn(echoPin1, HIGH);
|
||||||
|
|
||||||
|
|
||||||
// Calculating the distance
|
// Calculating the distance
|
||||||
distance = duration * 0.034 / 2;
|
distance1 = getDistance(duration1);
|
||||||
// Prints the distance on the Serial Monitor
|
|
||||||
/* if ((distance != (distance_alt - 1)) && (distance != (distance_alt)) && (distance != (distance_alt + 1))) { //+-1 um störungen herauszufiltern
|
// Prints the distance1 on the Serial Monitor
|
||||||
|
/* if ((distance1!= (distance_alt - 1)) && (distance1!= (distance_alt)) && (distance1!= (distance_alt + 1))) { //+-1 um störungen herauszufiltern
|
||||||
snprintf (msg, 50, "%d", distance);
|
snprintf (msg, 50, "%d", distance);
|
||||||
Serial.print("Publish Motion: ");
|
Serial.print("Publish Motion: ");
|
||||||
Serial.println(msg);
|
Serial.println(msg);
|
||||||
client.publish("/home/data", msg);
|
client.publish("/home/data", msg);
|
||||||
delay(200);
|
delay(200);
|
||||||
} */
|
} */
|
||||||
|
bool1 = presenceDetection(bool1, distance1);
|
||||||
|
|
||||||
|
|
||||||
|
delay(80);
|
||||||
|
}
|
||||||
|
|
||||||
|
int presenceDetection(int bool1, int distance1){
|
||||||
|
|
||||||
if (bool1 == 0) {
|
if (bool1 == 0) {
|
||||||
//alternativ: if ((distance != (DISTANCE - 1)) && (distance != (DISTANCE)) && (distance != (DISTANCE + 1))) { //+-1
|
//alternativ: if ((distance1!= (DISTANCE - 1)) && (distance1!= (DISTANCE)) && (distance1!= (DISTANCE + 1))) { //+-1
|
||||||
if (((DISTANCE + 2) < distance) || ((DISTANCE - 2) > distance)) { //darf +- 2 um festgelegte entfernung schwanken, um störungen herauszufiltern
|
|
||||||
|
if (((distance1 > (DISTANCE + 2)) || (distance1 < (DISTANCE - 2))) && (distance1 < (DISTANCE + 2))) { //darf +- 2 um festgelegte entfernung schwanken, um störungen herauszufiltern
|
||||||
//Meldung an PI, dass die Distanz gestört ist
|
//Meldung an PI, dass die Distanz gestört ist
|
||||||
snprintf (msg, 50, "%d", 1);
|
snprintf (msg, 50, "%d", 1);
|
||||||
client.publish("/gso/bb/104/ultraschall/1", msg);
|
client.publish("/gso/bb/104/ultraschall/1", msg);
|
||||||
//Serieller Monitor
|
//Serieller Monitor
|
||||||
Serial.print("Motion detected! Distance: ");
|
Serial.print("Motion detected! Distance: ");
|
||||||
Serial.println(distance);
|
Serial.println(distance1);
|
||||||
|
|
||||||
//Flag auf 1
|
//Flag auf 1
|
||||||
bool1 = 1;
|
bool1 = 1;
|
||||||
|
return bool1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
snprintf (msg, 50, "%d", 0);
|
snprintf (msg, 50, "%d", 0);
|
||||||
client.publish("/gso/bb/104/ultraschall/1", msg);
|
client.publish("/gso/bb/104/ultraschall/1", msg);
|
||||||
|
return bool1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (bool1 == 1) {
|
else if (bool1 == 1) {
|
||||||
if (((DISTANCE + 2) < distance) || ((DISTANCE - 2) > distance)) { //darf +- 2 um festgelegte entfernung schwanken, um störungen herauszufiltern
|
if (((distance1> (DISTANCE + 2)) || (distance1<(DISTANCE - 2)))) { //darf +- 2 um festgelegte entfernung schwanken, um störungen herauszufiltern
|
||||||
Serial.print("Still motion detected! Distance: ");
|
Serial.print("Still motion detected! Distance: ");
|
||||||
Serial.println(distance);
|
Serial.println(distance1);
|
||||||
//Meldung an PI, dass die Ausgangsdistanz wieder gemessen wird
|
//Meldung an PI, dass die Ausgangsdistanz wieder gemessen wird
|
||||||
snprintf (msg, 50, "%d", 1);
|
snprintf (msg, 50, "%d", 1);
|
||||||
client.publish("/gso/bb/104/ultraschall/1", msg);
|
client.publish("/gso/bb/104/ultraschall/1", msg);
|
||||||
|
|
||||||
|
return bool1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//Meldung an PI, dass die Ausgangsdistanz wieder gemessen wird
|
//Meldung an PI, dass die Ausgangsdistanz wieder gemessen wird
|
||||||
@ -126,8 +144,13 @@ void loop() {
|
|||||||
|
|
||||||
//Flag wieder auf 0
|
//Flag wieder auf 0
|
||||||
bool1 = 0;
|
bool1 = 0;
|
||||||
|
return bool1;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delay(100);
|
}
|
||||||
|
|
||||||
|
int getDistance(int duration){
|
||||||
|
int distance = duration * 0.034 / 2;
|
||||||
|
return distance;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,313 @@
|
|||||||
|
#include <Wire.h>
|
||||||
|
#include "MLX90640_API.h"
|
||||||
|
#include "MLX90640_I2C_Driver.h"
|
||||||
|
#include "SPI.h"
|
||||||
|
//#include "Adafruit_GFX.h"
|
||||||
|
//#include "Adafruit_ILI9341.h"
|
||||||
|
|
||||||
|
// For the ESP-WROVER_KIT, these are the default.
|
||||||
|
/*#define TFT_CS 15
|
||||||
|
#define TFT_DC 2
|
||||||
|
#define TFT_MOSI 13
|
||||||
|
#define TFT_CLK 14
|
||||||
|
#define TFT_RST 26
|
||||||
|
#define TFT_MISO 12
|
||||||
|
#define TFT_LED 27*/
|
||||||
|
|
||||||
|
/*Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);*/
|
||||||
|
|
||||||
|
const byte MLX90640_address = 0x33; //Default 7-bit unshifted address of the MLX90640
|
||||||
|
|
||||||
|
#define TA_SHIFT 8 //Default shift for MLX90640 in open air
|
||||||
|
|
||||||
|
static float mlx90640To[768];
|
||||||
|
paramsMLX90640 mlx90640;
|
||||||
|
|
||||||
|
int xPos, yPos; // Abtastposition
|
||||||
|
int R_colour, G_colour, B_colour; // RGB-Farbwert
|
||||||
|
int i, j; // Zählvariable
|
||||||
|
float T_max, T_min; // maximale bzw. minimale gemessene Temperatur
|
||||||
|
float T_center; // Temperatur in der Bildschirmmitte
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ***************************************
|
||||||
|
// **************** SETUP ****************
|
||||||
|
// ***************************************
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
Wire.begin();
|
||||||
|
Wire.setClock(400000); //Increase I2C clock speed to 400kHz
|
||||||
|
|
||||||
|
while (!Serial); //Wait for user to open terminal
|
||||||
|
|
||||||
|
Serial.println("MLX90640 IR Array Example");
|
||||||
|
|
||||||
|
if (isConnected() == false)
|
||||||
|
{
|
||||||
|
Serial.println("MLX90640 not detected at default I2C address. Please check wiring. Freezing.");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("MLX90640 online!");
|
||||||
|
|
||||||
|
//Get device parameters - We only have to do this once
|
||||||
|
int status;
|
||||||
|
uint16_t eeMLX90640[832];
|
||||||
|
|
||||||
|
status = MLX90640_DumpEE(MLX90640_address, eeMLX90640);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
Serial.println("Failed to load system parameters");
|
||||||
|
if (status == 0)
|
||||||
|
Serial.println("dumpee_okay");
|
||||||
|
|
||||||
|
status = MLX90640_ExtractParameters(eeMLX90640, &mlx90640);
|
||||||
|
|
||||||
|
if (status != 0)
|
||||||
|
{
|
||||||
|
Serial.println("Parameter extraction failed");
|
||||||
|
Serial.print(" status = ");
|
||||||
|
Serial.println(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Once params are extracted, we can release eeMLX90640 array
|
||||||
|
|
||||||
|
MLX90640_I2CWrite(0x33, 0x800D, 6401); // writes the value 1901 (HEX) = 6401 (DEC) in the register at position 0x800D to enable reading out the temperatures!!!
|
||||||
|
// ===============================================================================================================================================================
|
||||||
|
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x00); //Set rate to 0.25Hz effective - Works
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x01); //Set rate to 0.5Hz effective - Works
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x02); //Set rate to 1Hz effective - Works
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x03); //Set rate to 2Hz effective - Works
|
||||||
|
MLX90640_SetRefreshRate(MLX90640_address, 0x04); //Set rate to 4Hz effective - Works
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x05); //Set rate to 8Hz effective - Works at 800kHz
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x06); //Set rate to 16Hz effective - Works at 800kHz
|
||||||
|
//MLX90640_SetRefreshRate(MLX90640_address, 0x07); //Set rate to 32Hz effective - fails
|
||||||
|
|
||||||
|
|
||||||
|
//pinMode(TFT_LED, OUTPUT);
|
||||||
|
//digitalWrite(TFT_LED, HIGH);
|
||||||
|
|
||||||
|
/*tft.begin();
|
||||||
|
|
||||||
|
tft.setRotation(1);
|
||||||
|
|
||||||
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
tft.fillRect(0, 0, 319, 13, tft.color565(255, 0, 10));
|
||||||
|
tft.setCursor(100, 3);
|
||||||
|
tft.setTextSize(1);
|
||||||
|
tft.setTextColor(ILI9341_YELLOW, tft.color565(255, 0, 10));
|
||||||
|
tft.print("Thermographie - stoppi");
|
||||||
|
|
||||||
|
tft.drawLine(250, 210 - 0, 258, 210 - 0, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(250, 210 - 30, 258, 210 - 30, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(250, 210 - 60, 258, 210 - 60, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(250, 210 - 90, 258, 210 - 90, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(250, 210 - 120, 258, 210 - 120, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(250, 210 - 150, 258, 210 - 150, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(250, 210 - 180, 258, 210 - 180, tft.color565(255, 255, 255));
|
||||||
|
|
||||||
|
tft.setCursor(80, 220);
|
||||||
|
tft.setTextColor(ILI9341_WHITE, tft.color565(0, 0, 0));
|
||||||
|
tft.print("T+ = ");
|
||||||
|
|
||||||
|
|
||||||
|
// drawing the colour-scale
|
||||||
|
// ========================
|
||||||
|
|
||||||
|
for (i = 0; i < 181; i++)
|
||||||
|
{
|
||||||
|
//value = random(180);
|
||||||
|
|
||||||
|
getColour(i);
|
||||||
|
tft.drawLine(240, 210 - i, 250, 210 - i, tft.color565(R_colour, G_colour, B_colour));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
// **********************************
|
||||||
|
// ************** LOOP **************
|
||||||
|
// **********************************
|
||||||
|
|
||||||
|
void loop(){
|
||||||
|
for (byte x = 0 ; x < 2 ; x++) //Read both subpages
|
||||||
|
{
|
||||||
|
uint16_t mlx90640Frame[834];
|
||||||
|
int status = MLX90640_GetFrameData(MLX90640_address, mlx90640Frame);
|
||||||
|
|
||||||
|
if (status < 0)
|
||||||
|
{
|
||||||
|
Serial.print("GetFrame Error: ");
|
||||||
|
Serial.println(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
float vdd = MLX90640_GetVdd(mlx90640Frame, &mlx90640);
|
||||||
|
float Ta = MLX90640_GetTa(mlx90640Frame, &mlx90640);
|
||||||
|
|
||||||
|
float tr = Ta - TA_SHIFT; //Reflected temperature based on the sensor ambient temperature
|
||||||
|
float emissivity = 0.95;
|
||||||
|
|
||||||
|
MLX90640_CalculateTo(mlx90640Frame, &mlx90640, emissivity, tr, mlx90640To);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// determine T_min and T_max and eliminate error pixels
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
mlx90640To[1*32 + 21] = 0.5 * (mlx90640To[1*32 + 20] + mlx90640To[1*32 + 22]); // eliminate the error-pixels
|
||||||
|
mlx90640To[4*32 + 30] = 0.5 * (mlx90640To[4*32 + 29] + mlx90640To[4*32 + 31]); // eliminate the error-pixels
|
||||||
|
|
||||||
|
T_min = mlx90640To[0];
|
||||||
|
T_max = mlx90640To[0];
|
||||||
|
|
||||||
|
for (i = 1; i < 768; i++)
|
||||||
|
{
|
||||||
|
if((mlx90640To[i] > -41) && (mlx90640To[i] < 301))
|
||||||
|
{
|
||||||
|
if(mlx90640To[i] < T_min)
|
||||||
|
{
|
||||||
|
T_min = mlx90640To[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mlx90640To[i] > T_max)
|
||||||
|
{
|
||||||
|
T_max = mlx90640To[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(i > 0) // temperature out of range
|
||||||
|
{
|
||||||
|
mlx90640To[i] = mlx90640To[i-1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mlx90640To[i] = mlx90640To[i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// determine T_center
|
||||||
|
// ==================
|
||||||
|
|
||||||
|
T_center = mlx90640To[11* 32 + 15];
|
||||||
|
|
||||||
|
// drawing the picture
|
||||||
|
// ===================
|
||||||
|
|
||||||
|
for (i = 0 ; i < 24 ; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 32; j++)
|
||||||
|
{
|
||||||
|
mlx90640To[i*32 + j] = 180.0 * (mlx90640To[i*32 + j] - T_min) / (T_max - T_min);
|
||||||
|
|
||||||
|
getColour(mlx90640To[i*32 + j]);
|
||||||
|
|
||||||
|
// tft.fillRect(217 - j * 7, 35 + i * 7, 7, 7, tft.color565(R_colour, G_colour, B_colour));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
tft.drawLine(217 - 15*7 + 3.5 - 5, 11*7 + 35 + 3.5, 217 - 15*7 + 3.5 + 5, 11*7 + 35 + 3.5, tft.color565(255, 255, 255));
|
||||||
|
tft.drawLine(217 - 15*7 + 3.5, 11*7 + 35 + 3.5 - 5, 217 - 15*7 + 3.5, 11*7 + 35 + 3.5 + 5, tft.color565(255, 255, 255));
|
||||||
|
|
||||||
|
tft.fillRect(260, 25, 37, 10, tft.color565(0, 0, 0));
|
||||||
|
tft.fillRect(260, 205, 37, 10, tft.color565(0, 0, 0));
|
||||||
|
tft.fillRect(115, 220, 37, 10, tft.color565(0, 0, 0));
|
||||||
|
|
||||||
|
tft.setTextColor(ILI9341_WHITE, tft.color565(0, 0, 0));
|
||||||
|
tft.setCursor(265, 25);
|
||||||
|
tft.print(T_max, 1);
|
||||||
|
tft.setCursor(265, 205);
|
||||||
|
tft.print(T_min, 1);
|
||||||
|
tft.setCursor(120, 220);
|
||||||
|
tft.print(T_center, 1);
|
||||||
|
|
||||||
|
tft.setCursor(300, 25);
|
||||||
|
tft.print("C");
|
||||||
|
tft.setCursor(300, 205);
|
||||||
|
tft.print("C");
|
||||||
|
tft.setCursor(155, 220);
|
||||||
|
tft.print("C");
|
||||||
|
*/
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ===============================
|
||||||
|
// ===== determine the colour ====
|
||||||
|
// ===============================
|
||||||
|
|
||||||
|
void getColour(int j)
|
||||||
|
{
|
||||||
|
if (j >= 0 && j < 30)
|
||||||
|
{
|
||||||
|
R_colour = 0;
|
||||||
|
G_colour = 0;
|
||||||
|
B_colour = 20 + (120.0/30.0) * j;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j >= 30 && j < 60)
|
||||||
|
{
|
||||||
|
R_colour = (120.0 / 30) * (j - 30.0);
|
||||||
|
G_colour = 0;
|
||||||
|
B_colour = 140 - (60.0/30.0) * (j - 30.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j >= 60 && j < 90)
|
||||||
|
{
|
||||||
|
R_colour = 120 + (135.0/30.0) * (j - 60.0);
|
||||||
|
G_colour = 0;
|
||||||
|
B_colour = 80 - (70.0/30.0) * (j - 60.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j >= 90 && j < 120)
|
||||||
|
{
|
||||||
|
R_colour = 255;
|
||||||
|
G_colour = 0 + (60.0/30.0) * (j - 90.0);
|
||||||
|
B_colour = 10 - (10.0/30.0) * (j - 90.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j >= 120 && j < 150)
|
||||||
|
{
|
||||||
|
R_colour = 255;
|
||||||
|
G_colour = 60 + (175.0/30.0) * (j - 120.0);
|
||||||
|
B_colour = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j >= 150 && j <= 180)
|
||||||
|
{
|
||||||
|
R_colour = 255;
|
||||||
|
G_colour = 235 + (20.0/30.0) * (j - 150.0);
|
||||||
|
B_colour = 0 + 255.0/30.0 * (j - 150.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Returns true if the MLX90640 is detected on the I2C bus
|
||||||
|
boolean isConnected()
|
||||||
|
{
|
||||||
|
Wire.beginTransmission((uint8_t)MLX90640_address);
|
||||||
|
|
||||||
|
if (Wire.endTransmission() != 0)
|
||||||
|
return (false); //Sensor did not ACK
|
||||||
|
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
arduino/wärmebildkamera/Arduino_ESP32_MLX90640/MLX90640_API.zip
Normal file
BIN
arduino/wärmebildkamera/Arduino_ESP32_MLX90640/MLX90640_API.zip
Normal file
Binary file not shown.
Binary file not shown.
@ -0,0 +1,113 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
Read the temperature pixels from the MLX90640 IR array
|
||||||
|
By: Nathan Seidle
|
||||||
|
SparkFun Electronics
|
||||||
|
Date: May 22nd, 2018
|
||||||
|
License: MIT. See license file for more information but you can
|
||||||
|
basically do whatever you want with this code.
|
||||||
|
|
||||||
|
Feel like supporting open source hardware?
|
||||||
|
Buy a board from SparkFun! https://www.sparkfun.com/products/14769
|
||||||
|
|
||||||
|
This example initializes the MLX90640 and outputs the 768 temperature values
|
||||||
|
from the 768 pixels.
|
||||||
|
|
||||||
|
This example will work with a Teensy 3.1 and above. The MLX90640 requires some
|
||||||
|
hefty calculations and larger arrays. You will need a microcontroller with 20,000
|
||||||
|
bytes or more of RAM.
|
||||||
|
|
||||||
|
This relies on the driver written by Melexis and can be found at:
|
||||||
|
https://github.com/melexis/mlx90640-library
|
||||||
|
|
||||||
|
Hardware Connections:
|
||||||
|
Connect the SparkFun Qwiic Breadboard Jumper (https://www.sparkfun.com/products/14425)
|
||||||
|
to the Qwiic board
|
||||||
|
Connect the male pins to the Teensy. The pinouts can be found here: https://www.pjrc.com/teensy/pinout.html
|
||||||
|
Open the serial monitor at 9600 baud to see the output
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
#include "MLX90640_API.h"
|
||||||
|
#include "MLX90640_I2C_Driver.h"
|
||||||
|
|
||||||
|
const byte MLX90640_address = 0x33; //Default 7-bit unshifted address of the MLX90640
|
||||||
|
|
||||||
|
#define TA_SHIFT 8 //Default shift for MLX90640 in open air
|
||||||
|
|
||||||
|
static float mlx90640To[768];
|
||||||
|
paramsMLX90640 mlx90640;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Wire.begin();
|
||||||
|
Wire.setClock(100000); //Increase I2C clock speed to 400kHz
|
||||||
|
|
||||||
|
Serial.begin(9600);
|
||||||
|
while (!Serial); //Wait for user to open terminal
|
||||||
|
Serial.println("MLX90640 IR Array Example");
|
||||||
|
|
||||||
|
if (isConnected() == false)
|
||||||
|
{
|
||||||
|
Serial.println("MLX90640 not detected at default I2C address. Please check wiring. Freezing.");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
Serial.println("MLX90640 online!");
|
||||||
|
|
||||||
|
//Get device parameters - We only have to do this once
|
||||||
|
int status;
|
||||||
|
uint16_t eeMLX90640[832];
|
||||||
|
status = MLX90640_DumpEE(MLX90640_address, eeMLX90640);
|
||||||
|
if (status != 0)
|
||||||
|
Serial.println("Failed to load system parameters");
|
||||||
|
|
||||||
|
status = MLX90640_ExtractParameters(eeMLX90640, &mlx90640);
|
||||||
|
if (status != 0)
|
||||||
|
Serial.println("Parameter extraction failed");
|
||||||
|
|
||||||
|
//Once params are extracted, we can release eeMLX90640 array
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
for (byte x = 0 ; x < 2 ; x++) //Read both subpages
|
||||||
|
{
|
||||||
|
uint16_t mlx90640Frame[834];
|
||||||
|
int status = MLX90640_GetFrameData(MLX90640_address, mlx90640Frame);
|
||||||
|
if (status < 0)
|
||||||
|
{
|
||||||
|
Serial.print("GetFrame Error: ");
|
||||||
|
Serial.println(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
float vdd = MLX90640_GetVdd(mlx90640Frame, &mlx90640);
|
||||||
|
float Ta = MLX90640_GetTa(mlx90640Frame, &mlx90640);
|
||||||
|
|
||||||
|
float tr = Ta - TA_SHIFT; //Reflected temperature based on the sensor ambient temperature
|
||||||
|
float emissivity = 0.95;
|
||||||
|
|
||||||
|
MLX90640_CalculateTo(mlx90640Frame, &mlx90640, emissivity, tr, mlx90640To);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int x = 0 ; x < 10 ; x++)
|
||||||
|
{
|
||||||
|
Serial.print("Pixel ");
|
||||||
|
Serial.print(x);
|
||||||
|
Serial.print(": ");
|
||||||
|
Serial.print(mlx90640To[x], 2);
|
||||||
|
Serial.print("C");
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns true if the MLX90640 is detected on the I2C bus
|
||||||
|
boolean isConnected()
|
||||||
|
{
|
||||||
|
Wire.beginTransmission((uint8_t)MLX90640_address);
|
||||||
|
if (Wire.endTransmission() != 0)
|
||||||
|
return (false); //Sensor did not ACK
|
||||||
|
return (true);
|
||||||
|
}
|
BIN
arduino/wärmebildkamera/Example1_BasicReadings/MLX90640_API.zip
Normal file
BIN
arduino/wärmebildkamera/Example1_BasicReadings/MLX90640_API.zip
Normal file
Binary file not shown.
Binary file not shown.
1183
arduino/wärmebildkamera/MLX90640_API.cpp
Normal file
1183
arduino/wärmebildkamera/MLX90640_API.cpp
Normal file
File diff suppressed because it is too large
Load Diff
64
arduino/wärmebildkamera/MLX90640_API.h
Normal file
64
arduino/wärmebildkamera/MLX90640_API.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* @copyright (C) 2017 Melexis N.V.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _MLX640_API_H_
|
||||||
|
#define _MLX640_API_H_
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int16_t kVdd;
|
||||||
|
int16_t vdd25;
|
||||||
|
float KvPTAT;
|
||||||
|
float KtPTAT;
|
||||||
|
uint16_t vPTAT25;
|
||||||
|
float alphaPTAT;
|
||||||
|
int16_t gainEE;
|
||||||
|
float tgc;
|
||||||
|
float cpKv;
|
||||||
|
float cpKta;
|
||||||
|
uint8_t resolutionEE;
|
||||||
|
uint8_t calibrationModeEE;
|
||||||
|
float KsTa;
|
||||||
|
float ksTo[4];
|
||||||
|
int16_t ct[4];
|
||||||
|
float alpha[768];
|
||||||
|
int16_t offset[768];
|
||||||
|
float kta[768];
|
||||||
|
float kv[768];
|
||||||
|
float cpAlpha[2];
|
||||||
|
int16_t cpOffset[2];
|
||||||
|
float ilChessC[3];
|
||||||
|
uint16_t brokenPixels[5];
|
||||||
|
uint16_t outlierPixels[5];
|
||||||
|
} paramsMLX90640;
|
||||||
|
|
||||||
|
int MLX90640_DumpEE(uint8_t slaveAddr, uint16_t *eeData);
|
||||||
|
int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData);
|
||||||
|
int MLX90640_ExtractParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
|
||||||
|
float MLX90640_GetVdd(uint16_t *frameData, const paramsMLX90640 *params);
|
||||||
|
float MLX90640_GetTa(uint16_t *frameData, const paramsMLX90640 *params);
|
||||||
|
void MLX90640_GetImage(uint16_t *frameData, const paramsMLX90640 *params, float *result);
|
||||||
|
void MLX90640_CalculateTo(uint16_t *frameData, const paramsMLX90640 *params, float emissivity, float tr, float *result);
|
||||||
|
int MLX90640_SetResolution(uint8_t slaveAddr, uint8_t resolution);
|
||||||
|
int MLX90640_GetCurResolution(uint8_t slaveAddr);
|
||||||
|
int MLX90640_SetRefreshRate(uint8_t slaveAddr, uint8_t refreshRate);
|
||||||
|
int MLX90640_GetRefreshRate(uint8_t slaveAddr);
|
||||||
|
int MLX90640_GetSubPageNumber(uint16_t *frameData);
|
||||||
|
int MLX90640_GetCurMode(uint8_t slaveAddr);
|
||||||
|
int MLX90640_SetInterleavedMode(uint8_t slaveAddr);
|
||||||
|
int MLX90640_SetChessMode(uint8_t slaveAddr);
|
||||||
|
|
||||||
|
#endif
|
102
arduino/wärmebildkamera/MLX90640_I2C_Driver.cpp
Normal file
102
arduino/wärmebildkamera/MLX90640_I2C_Driver.cpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
@copyright (C) 2017 Melexis N.V.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include "MLX90640_I2C_Driver.h"
|
||||||
|
|
||||||
|
void MLX90640_I2CInit()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Read a number of words from startAddress. Store into Data array.
|
||||||
|
//Returns 0 if successful, -1 if error
|
||||||
|
int MLX90640_I2CRead(uint8_t _deviceAddress, unsigned int startAddress, unsigned int nWordsRead, uint16_t *data)
|
||||||
|
{
|
||||||
|
|
||||||
|
//Caller passes number of 'unsigned ints to read', increase this to 'bytes to read'
|
||||||
|
uint16_t bytesRemaining = nWordsRead * 2;
|
||||||
|
|
||||||
|
//It doesn't look like sequential read works. Do we need to re-issue the address command each time?
|
||||||
|
|
||||||
|
uint16_t dataSpot = 0; //Start at beginning of array
|
||||||
|
|
||||||
|
//Setup a series of chunked I2C_BUFFER_LENGTH byte reads
|
||||||
|
while (bytesRemaining > 0)
|
||||||
|
{
|
||||||
|
Wire.beginTransmission(_deviceAddress);
|
||||||
|
Wire.write(startAddress >> 8); //MSB
|
||||||
|
Wire.write(startAddress & 0xFF); //LSB
|
||||||
|
Wire.endTransmission(false)
|
||||||
|
uint16_t numberOfBytesToRead = bytesRemaining;
|
||||||
|
if (numberOfBytesToRead > I2C_BUFFER_LENGTH) numberOfBytesToRead = I2C_BUFFER_LENGTH;
|
||||||
|
|
||||||
|
Wire.requestFrom((uint8_t)_deviceAddress, numberOfBytesToRead);
|
||||||
|
if (Wire.available())
|
||||||
|
{
|
||||||
|
for (uint16_t x = 0 ; x < numberOfBytesToRead / 2; x++)
|
||||||
|
{
|
||||||
|
//Store data into array
|
||||||
|
data[dataSpot] = Wire.read() << 8; //MSB
|
||||||
|
data[dataSpot] |= Wire.read(); //LSB
|
||||||
|
|
||||||
|
dataSpot++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesRemaining -= numberOfBytesToRead;
|
||||||
|
|
||||||
|
startAddress += numberOfBytesToRead / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0); //Success
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set I2C Freq, in kHz
|
||||||
|
//MLX90640_I2CFreqSet(1000) sets frequency to 1MHz
|
||||||
|
void MLX90640_I2CFreqSet(int freq)
|
||||||
|
{
|
||||||
|
//i2c.frequency(1000 * freq);
|
||||||
|
Wire.setClock((long)1000 * freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Write two bytes to a two byte address
|
||||||
|
int MLX90640_I2CWrite(uint8_t _deviceAddress, unsigned int writeAddress, uint16_t data)
|
||||||
|
{
|
||||||
|
Wire.beginTransmission((uint8_t)_deviceAddress);
|
||||||
|
Wire.write(writeAddress >> 8); //MSB
|
||||||
|
Wire.write(writeAddress & 0xFF); //LSB
|
||||||
|
Wire.write(data >> 8); //MSB
|
||||||
|
Wire.write(data & 0xFF); //LSB
|
||||||
|
if (Wire.endTransmission() != 0)
|
||||||
|
{
|
||||||
|
//Sensor did not ACK
|
||||||
|
Serial.println("Error: Sensor did not ack");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t dataCheck;
|
||||||
|
MLX90640_I2CRead(_deviceAddress, writeAddress, 1, &dataCheck);
|
||||||
|
if (dataCheck != data)
|
||||||
|
{
|
||||||
|
//Serial.println("The write request didn't stick");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0); //Success
|
||||||
|
}
|
51
arduino/wärmebildkamera/MLX90640_I2C_Driver.h
Normal file
51
arduino/wärmebildkamera/MLX90640_I2C_Driver.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
@copyright (C) 2017 Melexis N.V.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#ifndef _MLX90640_I2C_Driver_H_
|
||||||
|
#define _MLX90640_I2C_Driver_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
//Define the size of the I2C buffer based on the platform the user has
|
||||||
|
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
|
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
|
||||||
|
|
||||||
|
//I2C_BUFFER_LENGTH is defined in Wire.H
|
||||||
|
#define I2C_BUFFER_LENGTH BUFFER_LENGTH
|
||||||
|
|
||||||
|
#elif defined(__SAMD21G18A__)
|
||||||
|
|
||||||
|
//SAMD21 uses RingBuffer.h
|
||||||
|
#define I2C_BUFFER_LENGTH SERIAL_BUFFER_SIZE
|
||||||
|
|
||||||
|
#elif __MK20DX256__
|
||||||
|
//Teensy 3.2
|
||||||
|
#define I2C_BUFFER_LENGTH 32
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
//The catch-all default is 32
|
||||||
|
#define I2C_BUFFER_LENGTH 32
|
||||||
|
|
||||||
|
#endif
|
||||||
|
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
|
|
||||||
|
|
||||||
|
void MLX90640_I2CInit(void);
|
||||||
|
int MLX90640_I2CRead(uint8_t slaveAddr, unsigned int startAddress, unsigned int nWordsRead, uint16_t *data);
|
||||||
|
int MLX90640_I2CWrite(uint8_t slaveAddr, unsigned int writeAddress, uint16_t data);
|
||||||
|
void MLX90640_I2CFreqSet(int freq);
|
||||||
|
#endif
|
9
arduino/wärmebildkamera/mlx90640/mlx90640.ino
Normal file
9
arduino/wärmebildkamera/mlx90640/mlx90640.ino
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
void setup() {
|
||||||
|
// put your setup code here, to run once:
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// put your main code here, to run repeatedly:
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user