티스토리 뷰
TouchDesigner
아두이노 나노 33 IoT _ 온습도, 조도,WIFI,GPS,OLED,TEMP,PULSE_SDcard_MQTT_TouchDesigner_00
잉_민 2024. 4. 24. 21:23728x90
반응형
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <Adafruit_MLX90614.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeMonoBold9pt7b.h>
#include <WiFiNINA.h>
#include <ArduinoMqttClient.h>
#include <RTCZero.h>
#include <Arduino.h>
#include "wiring_private.h"
#include <TinyGPSPlus.h>
#include <BH1750.h>
#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT22
#define BH1750_ADDRESS 0x23 // BH1750 조도센서의 I2C 주소
//ㄷ
#define PULSE_FILTER_SIZE 5
#define MLX90614_ADDRESS 0x5A
int pulseReadings[PULSE_FILTER_SIZE];
int pulseIndex = 0;
int totalPulse = 0;
//
//온습도 조도
BH1750 lightMeter(BH1750_ADDRESS);
DHT dht(DHTPIN, DHTTYPE);
char ssid[] = "TX_Lab"; // your network SSID (name)
char pass[] = "txtxxoxo123"; // your network password (use for WPA, or use as key for WEP)
// Define the pins for the GPS module connection
static const int RXPin =5, TXPin = 6;
static const uint32_t GPSBaud = 9600;
int count = 0;
const long interval = 1000 / 30; // 1초에 30개의 값을 보내기 위한 간격 (약 33.33ms)
unsigned long previousMillis = 0;
#define LED_BUILTIN 13
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
const char broker[] = "test.mosquitto.org";
int port = 1883;
const char topic[] = "arduino/data";
// time
RTCZero rtc;
Adafruit_SSD1306 display(128, 64);
Adafruit_MLX90614 mlx;
String fileName = "LSM_01.csv";
File myFile;
int temp;
const int FILTER_SIZE = 5;
float tempReadings[FILTER_SIZE];
int readIndex = 0;
float totalTemp = 0;
float filteredSignal = 0;
float alpha = 0.1;
int threshold = 700;
bool handPresent = false;
int PulseSensorPurplePin = A0;
char *dtostrf2(double val, signed char width, unsigned char prec, char *sout) {
char fmt[20];
sprintf(fmt, "%%%d.%df", width, prec);
sprintf(sout, fmt, val);
return sout;
}
// Create a TinyGPSPlus object
TinyGPSPlus gps;
// Setup for the new hardware serial port over SERCOM
Uart myGPS(&sercom0, RXPin, TXPin, SERCOM_RX_PAD_1, UART_TX_PAD_0);
void SERCOM0_Handler()
{
myGPS.IrqHandler();
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
// time
rtc.begin();
// Initialize Serial communication at 9600 baud
Serial.begin(9600);
// Initialize Serial1 communication at 9600 baud for the GPS module
myGPS.begin(GPSBaud);
// Assign pins to SERCOM functionality
pinPeripheral(RXPin, PIO_SERCOM_ALT);
pinPeripheral(TXPin, PIO_SERCOM_ALT);
Serial.println(F("DeviceExample.ino"));
Serial.println(F("A simple demonstration of TinyGPSPlus with an attached GPS module"));
Serial.print(F("Testing TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
Serial.println(F("by Mikal Hart"));
Serial.println();
// OLED 초기화
while (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("OLED initialization failed!");
delay(1000);
}
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
// 시작 메시지 표시
display.clearDisplay();
display.setCursor(28, 44);
display.println("Starting...");
display.display();
delay(1000);
// attempt to connect to WiFi network
display.clearDisplay();
display.setCursor(28, 44);
display.println("WiFi connecting...");
display.display();
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
delay(1000);
Serial.println("WiFi try...");
// 와이파이 연결 중 표시를 위해 LED를 깜박입니다.
digitalWrite(LED_BUILTIN , HIGH);
delay(100);
digitalWrite(LED_BUILTIN , LOW);
}
// 와이파이에 연결되었음을 표시하기 위해 LED를 3번 깜박입니다.
for (int i = 0; i < 3; i++) {
digitalWrite(LED_BUILTIN , HIGH);
delay(50);
digitalWrite(LED_BUILTIN , LOW);
delay(50);
}
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// WiFi 연결 완료 메시지 표시
display.clearDisplay();
display.setCursor(28, 34);
display.println("WiFi connected");
display.setCursor(28, 54);
display.println(WiFi.localIP());
display.display();
delay(2000);
// temp sensor 초기화
while (!mlx.begin(MLX90614_ADDRESS)) {
Serial.println("MLX90614 initialization failed!");
delay(1000);
}
// 온습도 센서 초기화
dht.begin();
delay(2000); // DHT 센서 초기화를 위한 대기 시간
if (isnan(dht.readHumidity()) || isnan(dht.readTemperature())) {
Serial.println("DHT22 initialization failed!");
while (1);
}
// 시작 메시지 표시
display.clearDisplay();
display.setCursor(28, 44);
display.println("temp...");
display.display();
delay(1000);
while (!SD.begin(10)) {
Serial.println("SD card initialization failed!");
delay(1000);
}
Serial.println("SD card initialization done.");
// 시작 메시지 표시
display.clearDisplay();
display.setCursor(28, 44);
display.println("SD...");
display.display();
delay(1000);
// 파일명 생성
while (SD.exists(fileName)) {
fileName = "LSM_" + String(fileName.substring(4, 6).toInt() + 1) + ".csv";
if (fileName.substring(4, 6).toInt() > 99) {
unsigned long currentTime = millis();
fileName = "LSM_" + String(currentTime) + ".csv";
break;
}
}
// 시작 메시지 표시
display.clearDisplay();
display.setCursor(28, 44);
display.println("file...");
display.display();
delay(1000);
myFile = SD.open(fileName, FILE_WRITE);
if (myFile) {
Serial.print("Writing to ");
Serial.print(fileName);
Serial.println("...");
myFile.println("Time, Ambient Temperature, Object Temperature, Pulse, Illuminance, Temperature, Humidity, Heat Index");
myFile.close();
Serial.println("done.");
} else {
Serial.print("error opening ");
Serial.println(fileName);
}
// 시작 메시지 표시
display.clearDisplay();
display.setCursor(28, 44);
display.println("open...");
display.display();
delay(1000);
for (int i = 0; i < FILTER_SIZE; i++) {
tempReadings[i] = 0;
}
// 시작 메시지 표시
display.clearDisplay();
display.setCursor(28, 44);
display.println("reading...");
display.display();
delay(1000);
while (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
delay(1000);
}
// 시작 메시지 표시
display.clearDisplay();
display.setCursor(28, 44);
display.println("mqtt...");
display.display();
delay(1000);
}
void loop() {
mqttClient.poll();
// Display information every time a new sentence is correctly encoded.
while (myGPS.available() > 0)
if (gps.encode(myGPS.read()))
displayInfo();
// If no GPS data is detected after 5 seconds, display a warning.
if (millis() > 5000 && gps.charsProcessed() < 10)
{
Serial.println(F("No GPS detected: check wiring."));
while(true);
}
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
float ambientTemp = mlx.readAmbientTempC();
float objectTemp = 0;
// 객체 온도 측정 및 이동평균 필터링
float tempReading = mlx.readObjectTempC();
if (tempReading >= 20 && tempReading <= 42) {
totalTemp -= tempReadings[readIndex];
tempReadings[readIndex] = tempReading;
totalTemp += tempReadings[readIndex];
readIndex = (readIndex + 1) % FILTER_SIZE;
objectTemp = totalTemp / FILTER_SIZE;
}
// 맥박값 이동평균 필터링
int signal = analogRead(PulseSensorPurplePin);
totalPulse -= pulseReadings[pulseIndex];
pulseReadings[pulseIndex] = signal;
totalPulse += pulseReadings[pulseIndex];
pulseIndex = (pulseIndex + 1) % PULSE_FILTER_SIZE;
filteredSignal = totalPulse / PULSE_FILTER_SIZE;
// Measure illuminance 온습도
uint16_t lux = lightMeter.readLightLevel();
// Measure temperature and humidity
float h = dht.readHumidity();
float t = dht.readTemperature();
// Calculate heat index in Celsius
float hic = dht.computeHeatIndex(t, h, false);
// OLED 디스플레이 업데이트
display.clearDisplay();
// 온도 값을 표시할 네모 그리기
display.drawRect(28, 18, 68, 24, WHITE);
display.setFont(&FreeMonoBold9pt7b);
display.setCursor(33, 38);
display.println(String(objectTemp, 1));
display.setCursor(78, 38);
display.println("C");
// 맥박 값 또는 "No hand" 텍스트를 표시할 네모 그리기
display.drawRect(28, 44, 68, 24, WHITE);
if (handPresent) {
display.setCursor(33, 62);
display.println(String(filteredSignal, 0));
} else {
display.setCursor(33, 62);
display.println("X");
}
display.display();
// SD 카드에 데이터 쓰기
myFile = SD.open(fileName, FILE_WRITE);
if (myFile) {
myFile.print(rtc.getEpoch()); // 현재 시간을 초 단위로 저장
myFile.print(", ");
myFile.print(ambientTemp);
myFile.print(", ");
myFile.print(objectTemp);
myFile.print(", ");
myFile.print(filteredSignal);
myFile.print(", ");
myFile.print(lux);
myFile.print(", ");
myFile.print(t);
myFile.print(", ");
myFile.print(h);
myFile.print(", ");
myFile.println(hic);
myFile.print(", ");
myFile.print(gps.location.lat(), 6);
myFile.print(", ");
myFile.print(gps.location.lng(), 6);
myFile.print(", ");
myFile.print(gps.date.year());
myFile.print("-");
myFile.print(gps.date.month());
myFile.print("-");
myFile.print(gps.date.day());
myFile.print(" ");
myFile.print(gps.time.hour());
myFile.print(":");
myFile.print(gps.time.minute());
myFile.print(":");
myFile.print(gps.time.second());
myFile.println();
myFile.close();
} else {
Serial.println("Error opening " + fileName);
}
// MQTT를 통해 데이터 전송
if (mqttClient.connected()) {
mqttClient.beginMessage(topic);
mqttClient.print("{ \"ambientTemp\": ");
mqttClient.print(ambientTemp);
mqttClient.print(", \"objectTemp\": ");
mqttClient.print(objectTemp);
mqttClient.print(", \"pulse\": ");
mqttClient.print(filteredSignal);
mqttClient.print(", \"illuminance\": ");
mqttClient.print(lux);
mqttClient.print(", \"temperature\": ");
mqttClient.print(t);
mqttClient.print(", \"humidity\": ");
mqttClient.print(h);
mqttClient.print(", \"heatIndex\": ");
mqttClient.print(hic);
// Include GPS values if valid
if (gps.location.isValid()) {
mqttClient.print(", \"latitude\": ");
mqttClient.print(gps.location.lat(), 6);
mqttClient.print(", \"longitude\": ");
mqttClient.print(gps.location.lng(), 6);
}
if (gps.date.isValid() && gps.time.isValid()) {
mqttClient.print(", \"date\": \"");
mqttClient.print(gps.date.year());
mqttClient.print("-");
mqttClient.print(gps.date.month());
mqttClient.print("-");
mqttClient.print(gps.date.day());
mqttClient.print("T");
mqttClient.print(gps.time.hour());
mqttClient.print(":");
mqttClient.print(gps.time.minute());
mqttClient.print(":");
mqttClient.print(gps.time.second());
mqttClient.print(".");
mqttClient.print(gps.time.centisecond());
mqttClient.print("Z\"");
}
mqttClient.println(" }");
mqttClient.endMessage();
}
}
delay(30);
}
void displayInfo()
{
Serial.println(F("google map link below:"));
if (gps.location.isValid())
{
Serial.print("http://www.google.com/maps/place/");
Serial.print(gps.location.lat(), 6);
Serial.print(F(","));
Serial.println(gps.location.lng(), 6);
}
else
{
Serial.print(F("INVALID"));
}
// Output date and time information
Serial.print(F("Date/Time:"));
if (gps.date.isValid())
{
Serial.print(gps.date.month());
Serial.print(F("/"));
Serial.print(gps.date.day());
Serial.print(F("/"));
Serial.print(gps.date.year());
}
else
{
Serial.print(F("INVALID"));
}
Serial.print(F(" "));
if (gps.time.isValid())
{
if (gps.time.hour() < 10) Serial.print(F("0"));
Serial.print(gps.time.hour());
Serial.print(F(":"));
if (gps.time.minute() < 10) Serial.print(F("0"));
Serial.print(gps.time.minute());
Serial.print(F(":"));
if (gps.time.second() < 10) Serial.print(F("0"));
Serial.print(gps.time.second());
Serial.print(F("."));
if (gps.time.centisecond() < 10) Serial.print(F("0"));
Serial.print(gps.time.centisecond());
}
else
{
Serial.print(F("INVALID"));
}
Serial.println();
}
이동평균 필터(Moving Average Filter)는 일정 구간의 데이터를 평균내어 출력하는 저역통과 필터(Low Pass Filter)의 일종입니다. 주로 노이즈를 제거하거나 신호를 평탄화하는 용도로 사용됩니다.
이동평균 필터는 다음과 같은 수식으로 표현할 수 있습니다:
y[i] = (x[i] + x[i-1] + ... + x[i-N+1]) / N
여기서,
- y[i]: 필터링된 출력값
- x[i]: 현재 입력값
- N: 이동평균 구간의 길이
예를 들어, N=5인 이동평균 필터는 현재 값과 이전 4개의 값을 더하여 5로 나눈 평균값을 출력합니다. 이렇게 하면 short-term fluctuation이 제거되고 신호가 평탄화됩니다.
이동평균 필터를 코드로 구현하면 다음과 같습니다:
const int FILTER_SIZE = 5;
float readings[FILTER_SIZE];
int readIndex = 0;
float total = 0;
float filteredValue = 0;
void setup() {
for (int i = 0; i < FILTER_SIZE; i++) {
readings[i] = 0;
}
}
void loop() {
float reading = analogRead(sensorPin);
total -= readings[readIndex];
readings[readIndex] = reading;
total += readings[readIndex];
readIndex = (readIndex + 1) % FILTER_SIZE;
filteredValue = total / FILTER_SIZE;
}
위 코드에서:
- FILTER_SIZE는 이동평균 구간의 길이입니다.
- readings 배열은 최근 FILTER_SIZE개의 센서 값을 저장합니다.
- readIndex는 readings 배열에 새로운 값을 저장할 인덱스를 가리킵니다.
- total은 readings 배열에 저장된 값들의 합입니다.
- loop() 함수에서는 새로운 센서 값을 읽어 readings 배열에 저장하고, total과 readIndex를 갱신합니다.
- 필터링된 값은 total을 FILTER_SIZE로 나누어 계산합니다.
이동평균 필터는 구현이 간단하고 메모리 사용량이 적어 임베디드 시스템에서 자주 사용됩니다. 다만 이동평균 구간의 길이(N)에 따라 출력 값의 지연(delay)이 발생할 수 있다는 점을 고려해야 합니다.
TD
>mqttclient1
>mqttclient1_callbacks
# me - this DAT
# MQTT 브로커 정보
subscribed_topic = "arduino/data"
# Called when connection established
# dat - the OP which is cooking
def onConnect(dat):
op("mqttclient1").subscribe(subscribed_topic)
return
# Called when connection failed
# dat - the OP which is cooking
# msg - reason for failure
def onConnectFailure(dat, msg):
print(f"Connection failed: {msg}")
return
# Called when current connection lost
# dat - the OP which is cooking
# msg - reason for failure
def onConnectionLost(dat, msg):
print(f"Connection lost: {msg}")
return
# Called when server receives subscription request
# dat - the OP which is cooking
def onSubscribe(dat):
print(f"Subscribed to topic: {subscribed_topic}")
return
# Called when subscription request fails.
# dat - the OP which is cooking
# msg - reason for failure
def onSubscribeFailure(dat, msg):
print(f"Subscription failed: {msg}")
return
# Called when server receives unsubscription request
# dat - the OP which is cooking
def onUnsubscribe(dat):
print(f"Unsubscribed from topic: {subscribed_topic}")
return
# Called when unsubscription request fails.
# dat - the OP which is cooking
# msg - reason for failure
def onUnsubscribeFailure(dat, msg):
print(f"Unsubscription failed: {msg}")
return
# Called when server receives publish request
# dat - the OP which is cooking
def onPublish(dat):
print("Publish request received")
return
# Called when new content received from server
# dat - the OP which is cooking
# topic - topic name of the incoming message
# payload - payload of the incoming message
# qos - qos flag for of the incoming message
# retained - retained flag of the incoming message
# dup - dup flag of the incoming message
def onMessage(dat, topic, payload, qos, retained, dup):
print(f"Received message - Topic: {topic}, Payload: {payload}, QoS: {qos}, Retained: {retained}, Dup: {dup}")
if topic == subscribed_topic:
try:
# Assuming payload is already a byte string as it comes from MQTT
data = payload.decode('utf-8')
print(f"Decoded payload: {data}")
# JSON parsing
import json
parsed_data = json.loads(data)
# Extracting values
ambientTemp = parsed_data.get("ambientTemp", 0) # Using .get for safer extraction
objectTemp = parsed_data.get("objectTemp", 0)
pulse = parsed_data.get("pulse", 0)
latitude = parsed_data.get("latitude",0)
longitude = parsed_data.get("longitude",0)
illuminance = parsed_data.get("illuminance",0)
temperature = parsed_data.get("temperature",0)
humidity = parsed_data.get("humidity",0)
date = parsed_data.get("date",0)
print(f"Received data - Pulse: {pulse}, Ambient Temperature: {ambientTemp}, Object Temperature: {objectTemp},Latitude:{latitude}, Longitude: {longitude}")
# TouchDesigner Integration: Append to table1 operator and keep rows count to 100
tableOp = op('table2') # Access the operator
# Append the received data as a new row
tableOp.appendRow([pulse, ambientTemp, objectTemp, latitude, longitude,illuminance,temperature,humidity,date])
# Keep the number of rows to 100
while tableOp.numRows > 300:
tableOp.deleteRow(0) # Delete the oldest row
except Exception as e:
print(f"Error parsing payload: {e}")
728x90
반응형
'TouchDesigner' 카테고리의 다른 글
터치디자이너 Grbl_CNC 제어 (X,Y... 지정된 위치) (0) | 2024.04.25 |
---|---|
TOUCHDESIGNER _ RANDOM GENERATOR (0) | 2024.04.25 |
터치디자이너 : 아두이노 _ 온습도 , 조도 //시리얼 통신 (2) | 2024.04.19 |
TouchDesinger_motor_arduino (0) | 2024.03.30 |
Touchdesigner_ AI model 불러오기 (.pth) (0) | 2024.03.17 |
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Express
- runwayai
- opencv
- 라즈베리파이
- 후디니
- colab
- Midjourney
- node.js
- CNC
- TouchDesigner
- MQTT
- Arduino
- three.js
- RNN
- docker
- Unity
- imgtoimg
- oculuspro
- google ai studio
- ai image generator
- ai film
- Python
- houdini
- VR
- sequelize
- 유니티
- AI
- krea
- DeepLeaning
- Java
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
글 보관함
반응형