forked from triffid/FiveD_on_Arduino
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtemp.c
224 lines (179 loc) · 4.26 KB
/
temp.c
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/*
temp.c
This file currently reads temp from a MAX6675 on the SPI bus.
temp fields are 14.2 fixed point, so temp_set(500) will set the temperature to 125 celsius, and temp_get() = 600 is reporting a temperature of 150 celsius.
the conversion to/from this unit is done in gcode.c, near:
if (next_target.M == 104)
next_target.S = decfloat_to_int(&read_digit, 4, 1);
and
// M105- get temperature
case 105:
uint16_t t = temp_get();
note that the MAX6675 can't do more than approx 5 conversions per second- we go for 4 so the timing isn't too tight
*/
#include "temp.h"
#ifndef SIMULATION
#include <avr/eeprom.h>
#endif
#include "clock.h"
#include "serial.h"
#include "sermsg.h"
#include "timer.h"
#include "dda.h"
#include "sersendf.h"
#include "debug.h"
#include "heater.h"
#ifdef TEMP_MAX6675
#endif
#ifdef TEMP_THERMISTOR
#include "analog.h"
#define NUMTEMPS 20
uint16_t temptable[NUMTEMPS][2] PROGMEM = {
{1, 841},
{54, 255},
{107, 209},
{160, 184},
{213, 166},
{266, 153},
{319, 142},
{372, 132},
{425, 124},
{478, 116},
{531, 108},
{584, 101},
{637, 93},
{690, 86},
{743, 78},
{796, 70},
{849, 61},
{902, 50},
{955, 34},
{1008, 3}
};
#endif
#ifdef TEMP_AD595
#include "analog.h"
#endif
#ifndef TEMP_MAX6675
#ifndef TEMP_THERMISTOR
#ifndef TEMP_AD595
#error none of TEMP_MAX6675, TEMP_THERMISTOR or TEMP_AD595 are defined! What type of temp sensor are you using?
#endif
#endif
#endif
#include "simulation.h"
uint16_t current_temp = 0;
uint16_t target_temp = 0;
uint8_t temp_flags = 0;
uint8_t temp_residency = 0;
#ifndef ABSDELTA
#define ABSDELTA(a, b) (((a) >= (b))?((a) - (b)):((b) - (a)))
#endif
uint16_t temp_read() {
uint16_t temp;
#ifdef TEMP_MAX6675
#ifdef PRR
PRR &= ~MASK(PRSPI);
#elif defined PRR0
PRR0 &= ~MASK(PRSPI);
#endif
SPCR = MASK(MSTR) | MASK(SPE) | MASK(SPR0);
// enable MAX6675
WRITE(SS, 0);
// ensure 100ns delay - a bit extra is fine
delay(1);
// read MSB
SPDR = 0;
for (;(SPSR & MASK(SPIF)) == 0;);
temp = SPDR;
temp <<= 8;
// read LSB
SPDR = 0;
for (;(SPSR & MASK(SPIF)) == 0;);
temp |= SPDR;
// disable MAX6675
WRITE(SS, 1);
temp_flags = 0;
if ((temp & 0x8002) == 0) {
// got "device id"
temp_flags |= TEMP_FLAG_PRESENT;
if (temp & 4) {
// thermocouple open
temp_flags |= TEMP_FLAG_TCOPEN;
}
else {
current_temp = temp >> 3;
return current_temp;
}
}
#endif /* TEMP_MAX6675 */
#ifdef TEMP_THERMISTOR
uint8_t i;
//Read current temperature
temp = analog_read(TEMP_PIN_CHANNEL);
//Calculate real temperature based on lookup table
for (i = 1; i < NUMTEMPS; i++) {
if (pgm_read_word(&(temptable[i][0])) > temp) {
// multiply by 4 because internal temp is stored as 14.2 fixed point
temp = pgm_read_word(&(temptable[i][1])) + (pgm_read_word(&(temptable[i][0])) - temp) * 4 * (pgm_read_word(&(temptable[i-1][1])) - pgm_read_word(&(temptable[i][1]))) / (pgm_read_word(&(temptable[i][0])) - pgm_read_word(&(temptable[i-1][0])));
break;
}
}
//Clamp for overflows
if (i == NUMTEMPS)
temp = temptable[NUMTEMPS-1][1];
return temp;
#endif /* TEMP_THERMISTOR */
#ifdef TEMP_AD595
temp = analog_read(TEMP_PIN_CHANNEL);
// convert
// >>8 instead of >>10 because internal temp is stored as 14.2 fixed point
temp = (temp * 500L) >> 8;
return temp;
#endif /* TEMP_AD595 */
return 0;
}
void temp_set(uint16_t t) {
if (t) {
steptimeout = 0;
power_on();
}
target_temp = t;
}
uint16_t temp_get() {
return current_temp;
}
uint16_t temp_get_target() {
return target_temp;
}
void temp_print() {
if (temp_flags & TEMP_FLAG_TCOPEN) {
serial_writestr_P(PSTR("T: no thermocouple!\n"));
}
else {
uint8_t c = 0, t = 0;
c = (current_temp & 3) * 25;
t = (target_temp & 3) * 25;
#ifdef REPRAP_HOST_COMPATIBILITY
sersendf_P(PSTR(" T: %u.%u\n"), current_temp >> 2, c);
#else
sersendf_P(PSTR("T: %u.%u/%u.%u :%u\n"), current_temp >> 2, c, target_temp >> 2, t, temp_residency);
#endif
}
}
void temp_tick() {
if (target_temp) {
steptimeout = 0;
temp_read();
heater_tick(current_temp, target_temp);
if (ABSDELTA(current_temp, target_temp) > TEMP_HYSTERESIS)
temp_residency = 0;
else if (temp_residency < TEMP_RESIDENCY_TIME)
temp_residency++;
}
}
uint8_t temp_achieved() {
if (temp_residency >= TEMP_RESIDENCY_TIME)
return 255;
return 0;
}