본문 바로가기

3D Printer/OctoPrint

Chamber Manager Board 제작 #5 (Fan Control Class 제작)

【 3D 프린터 챔버 만들기 】



[ Control Board 제작 #5 : Fan Control Class 제작 ]




□ 필요사항


 : Timer1을 사용하여 Pin 9 또는 Pin 10에 25KHz PWM 출력


 : RPM은 인터럽트를 사용하지 않고, 주기적으로 RPM Reading Pin 상태를 감시하여 계산



[ FanControl.h ]


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
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef FANCONTROL_H
#define FANCONTROL_H
 
#if defined(ARDUINO) && (ARDUINO >= 100)
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif
 
#include <inttypes.h>
 
class FANControl
{
    private:
        class FANControl *next;
        static FANControl* first;
 
        unsigned long m_nMilsCheck;
 
        static int m_nPinControl;
        static bool m_bFansOn;
 
        int m_nPinReadRPM;
        int m_nPinWriteRPM;
 
    int m_nPinValue;
        int m_nRPM;
 
    public:
        FANControl();
        static void InitFanTimer();
        void Attach(int pinWrite, int pinRead);
        void Detach();
        int ReadRPM();
        bool IsAttached();
        static void Refresh();
        void SetSpeed(int speed);
        void FanOn();
        void FanOff();
};
 
#endif
cs



[ FanControl.cpp ]


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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "FanControl.h"
 
//////////////////////////////////////////////////////////////
//   Fans setup, PWM fans needs 25kHz PWM control (21~28kHz)
//   ex) 75Hz : 75/2*60 = 2,250rpm
//////////////////////////////////////////////////////////////
//      rpm     rps    sec  msec
//      100   1.667  0.600   600
//      200   3.333  0.300   300
//      300   5.000  0.200   200
//      400   6.667  0.150   150
//      500   8.333  0.120   120
//      600  10.000  0.100   100
//      700  11.667  0.086    86
//      800  13.333  0.075    75
//      900  15.000  0.067    67
//    1,000  16.667  0.060    60
//    1,100  18.333  0.055    55
//    1,200  20.000  0.050    50
//    1,300  21.667  0.046    46
//    1,400  23.333  0.043    43
//    1,500  25.000  0.040    40
//    1,600  26.667  0.038    38
//    1,700  28.333  0.035    35
//    1,800  30.000  0.033    33
//    1,900  31.667  0.032    32
//    2,000  33.333  0.030    30
//    2,100  35.000  0.029    29
//    2,200  36.667  0.027    27
//    2,300  38.333  0.026    26
//    2,400  40.000  0.025    25
 
#define FAN_FREQ            25000// PWM fans needs 25kHz PWM control
 
FANControl *FANControl::first;
int FANControl::m_nPinControl;
bool FANControl::m_bFansOn = false;
 
FANControl::FANControl()
{
  next = 0;
  m_nMilsCheck = 0;
 
  m_nPinReadRPM = 0;
  m_nPinWriteRPM = 0;
  m_nPinValue = 0;
  m_nRPM = 0;
 
}
 
void FANControl::InitFanTimer()
{
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  TCCR1A = _BV(COM1A1)  // non-inverted PWM on ch. A
        | _BV(COM1B1)   // same on ch. B
        | _BV(WGM11);   // mode 10: ph. correct PWM, TOP = ICR1
  TCCR1B = _BV(WGM13)   // ditto
        | _BV(CS11);    // prescaler = 8
  ICR1   = 40;
}
 
void FANControl::Attach(int pinWrite, int pinRead)
{
  next = first;
  first = this;
  
  m_nPinReadRPM = pinRead;
  pinMode(pinRead,INPUT_PULLUP);
  m_nPinValue = digitalRead(pinRead);
 
  m_nPinWriteRPM = pinWrite;
  pinMode(m_nPinWriteRPM, OUTPUT);
}
 
void FANControl::Detach()
{
  for ( FANControl **= &first; *!= 0; p = &((*p)->next) )
  {
    if ( *== this)
    {
      *= this->next;
      this->next = 0;
      digitalWrite(this->m_nPinWriteRPM, LOW);
      return;
    }
  }
}
 
bool FANControl::IsAttached()
{
  for ( FANControl *= first; p != 0; p = p->next )
  {
    if ( p == thisreturn true;
  }
  return false;
}
 
int FANControl::ReadRPM()
{
  return m_nRPM;
}
 
void FANControl::SetSpeed(int speed)
{
  analogWrite(m_nPinWriteRPM, map(speed, 0100040));
}
 
void FANControl::FanOn()
{
  SetSpeed(100);  
}
 
void FANControl::FanOff()
{
  SetSpeed(0);
}
 
void FANControl::Refresh()
{
  FANControl *p;
  uint8_t value;
  unsigned long m = millis();
  unsigned long diff;
  
  for(p=first; p!=0; p=p->next)
  {
    value = digitalRead(p->m_nPinReadRPM);
    if(p->m_nPinValue != value)
    {
      p->m_nPinValue = value;
        diff = m - p->m_nMilsCheck;
        p->m_nRPM = (uint16_t)(15000/diff); // Convert to half signal duration to rpm : 0.5 * 0.5 * 1000 msec *  60sec / duration(msec)
        p->m_nMilsCheck = m;
    }
    else
    {
      if((m - p->m_nMilsCheck)>400) p->m_nRPM = 0;
    }
  }
  
}
cs


EOL