HCI/Arduino

[Arduino] dual thermal feedback

sillon 2025. 5. 22. 20:35
728x90
반응형

오늘은 기기를 만들었습니다.

 

사용한 부품 및 장치

 

 

진동자: Hapcoil-one

가속도계: ADXL354

https://sillon-coding.tistory.com/632

 

[Haptics - Haptuator Single Frequency] Calibration Using NI DAQ and Python

1. 실험 개요진동자를 활용한 가속도 측정에서는 신호의 정확한 보정이 필수적입니다. 본 실험에서는 Single Frequency Calibration을 수행하여, 특정 주파수에서 입력 전압과 출력 가속도 값의 관계를

sillon-coding.tistory.com

펠티어모듈 : thermoREAL

서미스터(온도 측정)

아두이노 모터 드라이버 2A L298N / Arduino Motor driver

아두이노 우노

 

근데 뭔지는 안알려줄거임 ㅋ

 

개멋있어 강수연

 

회로는 아래와 같습니다

 

 

#include <PID_v1.h>

#define PWM 10
#define PHASE1 2
#define PHASE2 3

#define PWM2 11
#define PHASE3 4
#define PHASE4 5

int Vi = 1023;
float R1 = 22000;
float c1 = -1.185559046e-03;
float c2 = 5.505203063e-04;
float c3 = -9.653138374e-07;

// Sensor 1 (A0)
double input = 0, output = 0, prevInput = 0;
double init_setpoint = 32.5;
double setpoint = init_setpoint;

// Sensor 2 (A1)
double input2 = 0, output2 = 0, prevInput2 = 0;
double init_setpoint2 = 32.5;
double setpoint2 = init_setpoint2;

// PID Parameters
double Kp = 60, Ki = 0.6, Kd = 0.5;

PID myPID(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);
PID myPID2(&input2, &output2, &setpoint2, Kp, Ki, Kd, DIRECT);

String serialBuffer = "";

void setup() {
  Serial.begin(115200);

  pinMode(PWM, OUTPUT);    pinMode(PHASE1, OUTPUT);    pinMode(PHASE2, OUTPUT);
  pinMode(PWM2, OUTPUT);   pinMode(PHASE3, OUTPUT);    pinMode(PHASE4, OUTPUT);

  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(-255, 255);

  myPID2.SetMode(AUTOMATIC);
  myPID2.SetOutputLimits(-255, 255);

  Serial.println("READY");
}

void loop() {
if (Serial.available()) {
  String inputLine = Serial.readStringUntil('\n');
  inputLine.trim();  // 앞뒤 공백 제거

  int spaceIndex = inputLine.indexOf(' ');  // 공백 위치 찾기
  if (spaceIndex > 0) {
    String part1 = inputLine.substring(0, spaceIndex);
    String part2 = inputLine.substring(spaceIndex + 1);

    float delta1 = part1.toFloat();
    float delta2 = part2.toFloat();

    setpoint = init_setpoint + delta1;
    setpoint2 = init_setpoint2 + delta2;

    // 디버그 출력
    Serial.print("[INPUT OK] delta1: ");
    Serial.print(delta1);
    Serial.print(" → setpoint1: ");
    Serial.println(setpoint);

    Serial.print("[INPUT OK] delta2: ");
    Serial.print(delta2);
    Serial.print(" → setpoint2: ");
    Serial.println(setpoint2);
  } else {
    Serial.println("[ERROR] Input must be two space-separated numbers, like: 5 -3");
  }
}

  // Sensor 1
  double rawInput = ReadTemperature(A0);
  input = 0.4 * prevInput + 0.6 * rawInput;
  prevInput = input;

  // Sensor 2
  double rawInput2 = ReadTemperature(A1);
  input2 = 0.4 * prevInput2 + 0.6 * rawInput2;
  prevInput2 = input2;

  myPID.Compute();
  myPID2.Compute();

  SetOutputDirection(output, input, setpoint, PWM, PHASE1, PHASE2);
  SetOutputDirection(output2, input2, setpoint2, PWM2, PHASE3, PHASE4);

  // Pretty one-line status output
  Serial.print("CH1: ");
  Serial.print(input, 2);
  Serial.print("°C → ");
  Serial.print(setpoint, 2);
  Serial.print("°C | PWM: ");
  Serial.print(abs(output), 0);

  Serial.print("  ||  CH2: ");
  Serial.print(input2, 2);
  Serial.print("°C → ");
  Serial.print(setpoint2, 2);
  Serial.print("°C | PWM: ");
  Serial.println(abs(output2), 0);

  delay(100);  // 10Hz
}

double ReadTemperature(int pin) {
  int Vo = analogRead(pin);
  if (Vo <= 0) return -999.0;
  float R2 = R1 * (Vi / (float)Vo - 1.0);
  float logR2 = log(R2);
  return (1.0 / (c1 + c2 * logR2 + c3 * pow(logR2, 3))) - 273.15;
}

void SetOutputDirection(double out, double inTemp, double targetTemp,
                        int pwmPin, int ph1, int ph2) {
  double pwmVal = abs(out);
  digitalWrite(ph1, inTemp < targetTemp ? LOW : HIGH);
  digitalWrite(ph2, inTemp < targetTemp ? HIGH : LOW);
  analogWrite(pwmPin, pwmVal);
}

입력예시

3 -6

 

32.5 도가 기본 온도임

저렇게 입력하면 한쪽 펠티어에 32.5 + 3 = 35.5 도로 제어되고,

다른 한쪽에선 32.5 - 6 = 26.5도로 제어됨

728x90
반응형