Merge branch 'lcd2'
This commit is contained in:
BIN
CAD/3D/IEC-socket+switch.SLDPRT
Normal file
BIN
CAD/3D/IEC-socket+switch.SLDPRT
Normal file
Binary file not shown.
BIN
CAD/3D/LCD.SLDPRT
Normal file
BIN
CAD/3D/LCD.SLDPRT
Normal file
Binary file not shown.
394634
CAD/3D/OUTPUT/UM2_case.gcode
Normal file
394634
CAD/3D/OUTPUT/UM2_case.gcode
Normal file
File diff suppressed because it is too large
Load Diff
19350
CAD/3D/OUTPUT/case-display-holder.STL
Normal file
19350
CAD/3D/OUTPUT/case-display-holder.STL
Normal file
File diff suppressed because it is too large
Load Diff
126492
CAD/3D/OUTPUT/case.STL
Normal file
126492
CAD/3D/OUTPUT/case.STL
Normal file
File diff suppressed because it is too large
Load Diff
BIN
CAD/3D/OUTPUT/drill template.pdf
Normal file
BIN
CAD/3D/OUTPUT/drill template.pdf
Normal file
Binary file not shown.
BIN
CAD/3D/PSU_5V.SLDPRT
Normal file
BIN
CAD/3D/PSU_5V.SLDPRT
Normal file
Binary file not shown.
BIN
CAD/3D/SSR40.SLDPRT
Normal file
BIN
CAD/3D/SSR40.SLDPRT
Normal file
Binary file not shown.
BIN
CAD/3D/case-display-holder.SLDPRT
Normal file
BIN
CAD/3D/case-display-holder.SLDPRT
Normal file
Binary file not shown.
BIN
CAD/3D/case.SLDPRT
Normal file
BIN
CAD/3D/case.SLDPRT
Normal file
Binary file not shown.
BIN
CAD/3D/dril_template.SLDDRW
Normal file
BIN
CAD/3D/dril_template.SLDDRW
Normal file
Binary file not shown.
BIN
CAD/3D/heatplate_case.SLDASM
Normal file
BIN
CAD/3D/heatplate_case.SLDASM
Normal file
Binary file not shown.
BIN
CAD/Datasheet/MAX31855.pdf
Normal file
BIN
CAD/Datasheet/MAX31855.pdf
Normal file
Binary file not shown.
3
reflow_plate_fw/.vscode/settings.json
vendored
Normal file
3
reflow_plate_fw/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"C_Cpp.errorSquiggles": "Disabled"
|
||||
}
|
||||
99
reflow_plate_fw/include/ILI9341_STM32.h
Normal file
99
reflow_plate_fw/include/ILI9341_STM32.h
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Setup for STM32 Nucleo and ILI9341 display //
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
// Last update by Bodmer: 28/11/19
|
||||
|
||||
// STM32 optimised functions are not yet compatible with STM32H743 processor.
|
||||
// The STM32H743 does work with the slower generic processor drivers
|
||||
//
|
||||
// REMINDER - Nucleo-F743ZI and Nucleo-F743ZI2 have different pin port allocations
|
||||
// and require appropriate selection in IDE. ^---- Note the extra 2 in part number!
|
||||
|
||||
|
||||
// Define STM32 to invoke STM32 optimised driver
|
||||
#define STM32
|
||||
|
||||
// Define the TFT display driver
|
||||
#define ILI9341_DRIVER
|
||||
//#define ILI9481_DRIVER
|
||||
|
||||
// MOSI and SCK do not need to be defined, connect:
|
||||
// - Arduino SCK to TFT SCK
|
||||
// - Arduino MOSI to TFT SDI(may be marked SDA or MOSI)
|
||||
// Typical Arduino SPI port 1 pins are (SCK=D13, MISO=D12, MOSI=D11) this is port pins PA5, PA6 and PA7 on Nucleo-F767ZI
|
||||
// SPI port 2 pins are (SCK=D18, MISO=A7, MOSI=D17) this is port pins PB13, PC2 and PB15 on Nucleo-F767ZI
|
||||
|
||||
//#define TFT_MOSI PA7
|
||||
//#define TFT_SCLK PA5
|
||||
#define TFT_DC PB1
|
||||
#define TFT_RST PA8
|
||||
#define TFT_CS PB0
|
||||
|
||||
|
||||
#define TFT_SPI_PORT 1 // SPI 1 maximum clock rate is 55MHz
|
||||
#define TFT_MOSI PA7
|
||||
#define TFT_MISO PA6
|
||||
#define TFT_SCLK PA5
|
||||
|
||||
|
||||
/*
|
||||
#define TFT_SPI_PORT 2 // SPI 2 maximum clock rate is 27MHz
|
||||
#define TFT_MOSI D17
|
||||
#define TFT_MISO A7
|
||||
#define TFT_SCLK D18
|
||||
//*/
|
||||
|
||||
/*
|
||||
#define TFT_SPI_PORT 2 // SPI 2 maximum clock rate is 27MHz
|
||||
#define TFT_MOSI PB15
|
||||
#define TFT_MISO PC2
|
||||
#define TFT_SCLK PB13
|
||||
//*/
|
||||
|
||||
/*
|
||||
#define TFT_SPI_PORT 2 // SPI 2 maximum clock rate is 27MHz
|
||||
#define TFT_MOSI PB15
|
||||
#define TFT_MISO PB14
|
||||
#define TFT_SCLK PB13
|
||||
//*/
|
||||
|
||||
// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select
|
||||
// #define TFT_CS D5 // Chip select control pin to TFT CS
|
||||
// #define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select)
|
||||
// #define TFT_RST D7 // Reset pin to TFT RST (or RESET)
|
||||
|
||||
// Alternatively, we can use STM32 port reference names PXnn
|
||||
//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5
|
||||
//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6
|
||||
//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7
|
||||
|
||||
//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset
|
||||
// Use an Arduino pin for initial testing as connecting to processor reset
|
||||
// may not work (pulse too short at power up?)
|
||||
|
||||
// Chip select for XPT2046 touch controller
|
||||
#define TOUCH_CS PB2
|
||||
|
||||
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
|
||||
// STM32 support for smooth fonts via program memory (FLASH) arrays
|
||||
#define SMOOTH_FONT
|
||||
|
||||
|
||||
#define SPI_FREQUENCY 27000000 // 27MHz SPI clock
|
||||
//#define SPI_FREQUENCY 55000000 // 55MHz is over-clocking ILI9341 but seems to work reliably!
|
||||
|
||||
#define SPI_READ_FREQUENCY 15000000 // Reads need a slower SPI clock, probably ends up at 13.75MHz (CPU clock/16)
|
||||
|
||||
#define SPI_TOUCH_FREQUENCY 2500000 // Must be very slow
|
||||
|
||||
// This has no effect, transactions for STM32 are automatically enabled
|
||||
#define SUPPORT_TRANSACTIONS
|
||||
@@ -1,39 +0,0 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
||||
@@ -1,33 +0,0 @@
|
||||
// See SetupX_Template.h for all options available
|
||||
|
||||
#define SSD1351_DRIVER
|
||||
|
||||
#define TFT_WIDTH 128
|
||||
#define TFT_HEIGHT 128
|
||||
|
||||
#define STM32
|
||||
#define TFT_SPI_PORT 1
|
||||
|
||||
#define SSD1351_1DOT5_INCH_128 // For 128 x 128 display
|
||||
|
||||
//#define TFT_MOSI PA7
|
||||
//#define TFT_SCLK PA5
|
||||
#define TFT_DC PB1
|
||||
#define TFT_RST PA12
|
||||
#define TFT_CS PB0
|
||||
|
||||
|
||||
|
||||
#define LOAD_GLCD // Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||
#define LOAD_FONT2 // Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT4 // Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||
#define LOAD_FONT6 // Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||
#define LOAD_FONT7 // 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
|
||||
#define LOAD_FONT8 // Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||
//#define LOAD_FONT8N // Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
|
||||
#define LOAD_GFXFF // FreeFonts- 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||
#define SMOOTH_FONT
|
||||
|
||||
|
||||
#define SPI_FREQUENCY 20000000
|
||||
//#define SPI_FREQUENCY 40000000 // Works after shielding the wires!
|
||||
277
reflow_plate_fw/lib/ft6206_touch/ft6206_touch.cpp
Normal file
277
reflow_plate_fw/lib/ft6206_touch/ft6206_touch.cpp
Normal file
@@ -0,0 +1,277 @@
|
||||
#include "ft6206_touch.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Instantiates a new FT6206 class
|
||||
*/
|
||||
/**************************************************************************/
|
||||
// I2C, no address adjustments or pins
|
||||
FT6206::FT6206() { touches = 0; }
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Setups the I2C interface and hardware, identifies if chip is found
|
||||
@param thresh Optional threshhold-for-touch value, default is
|
||||
FT6206_DEFAULT_THRESSHOLD but you can try changing it if your screen is
|
||||
too/not sensitive.
|
||||
@returns True if an FT6206 is found, false on any failure
|
||||
*/
|
||||
/**************************************************************************/
|
||||
// bool begin(uint8_t thresh = FT62XX_DEFAULT_THRESHOLD, uint16_t width, uint16_t height, bool flip );
|
||||
|
||||
bool FT6206::begin(uint8_t sda, uint8_t scl, uint16_t width, uint16_t height, bool flip, uint8_t thresh) {
|
||||
Wire.begin(sda, scl);
|
||||
_width = width;
|
||||
_height = height;
|
||||
_flip = flip;
|
||||
#ifdef FT6206_DEBUG
|
||||
Serial.print("Vend ID: 0x");
|
||||
Serial.println(readRegister8(FT62XX_REG_VENDID), HEX);
|
||||
Serial.print("Chip ID: 0x");
|
||||
Serial.println(readRegister8(FT62XX_REG_CHIPID), HEX);
|
||||
Serial.print("Firm V: ");
|
||||
Serial.println(readRegister8(FT62XX_REG_FIRMVERS));
|
||||
Serial.print("Point Rate Hz: ");
|
||||
Serial.println(readRegister8(FT62XX_REG_POINTRATE));
|
||||
Serial.print("Thresh: ");
|
||||
Serial.println(readRegister8(FT62XX_REG_THRESHHOLD));
|
||||
|
||||
// dump all registers
|
||||
for (int16_t i = 0; i < 0x10; i++) {
|
||||
Serial.print("I2C $");
|
||||
Serial.print(i, HEX);
|
||||
Serial.print(" = 0x");
|
||||
Serial.println(readRegister8(i), HEX);
|
||||
}
|
||||
#endif
|
||||
|
||||
// change threshhold to be higher/lower
|
||||
writeRegister8(FT62XX_REG_THRESHHOLD, thresh);
|
||||
|
||||
if (readRegister8(FT62XX_REG_VENDID) != FT62XX_VENDID) {
|
||||
return false;
|
||||
}
|
||||
uint8_t id = readRegister8(FT62XX_REG_CHIPID);
|
||||
if ((id != FT6206_CHIPID) && (id != FT6236_CHIPID) &&
|
||||
(id != FT6236U_CHIPID)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Determines if there are any touches detected
|
||||
@returns Number of touches detected, can be 0, 1 or 2
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint8_t FT6206::touched(void) {
|
||||
uint8_t n = readRegister8(FT62XX_REG_NUMTOUCHES);
|
||||
if (n > 2) {
|
||||
n = 0;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Queries the chip and retrieves a point data
|
||||
@param n The # index (0 or 1) to the points we can detect. In theory we can
|
||||
detect 2 points but we've found that you should only use this for
|
||||
single-touch since the two points cant share the same half of the screen.
|
||||
@returns {@link TS_Point} object that has the x and y coordinets set. If the
|
||||
z coordinate is 0 it means the point is not touched. If z is 1, it is
|
||||
currently touched.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
TS_Point FT6206::getPoint(uint8_t n) {
|
||||
readData();
|
||||
if ((touches == 0) || (n > 1)) {
|
||||
return TS_Point(0, 0, 0);
|
||||
} else {
|
||||
if(_flip)
|
||||
{
|
||||
return TS_Point(_width - touchX[n], _height - touchY[n], 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TS_Point(touchX[n], touchY[n], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************ lower level i/o **************/
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Reads the bulk of data from captouch chip. Fill in {@link touches},
|
||||
{@link touchX}, {@link touchY} and {@link touchID} with results
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void FT6206::readData(void) {
|
||||
|
||||
uint8_t i2cdat[16];
|
||||
Wire.beginTransmission(FT62XX_ADDR);
|
||||
Wire.write((byte)0);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom((byte)FT62XX_ADDR, (byte)16);
|
||||
for (uint8_t i = 0; i < 16; i++)
|
||||
i2cdat[i] = Wire.read();
|
||||
|
||||
#ifdef FT6206_DEBUG
|
||||
for (int16_t i = 0; i < 16; i++) {
|
||||
Serial.print("I2C $");
|
||||
Serial.print(i, HEX);
|
||||
Serial.print(" = 0x");
|
||||
Serial.println(i2cdat[i], HEX);
|
||||
}
|
||||
#endif
|
||||
|
||||
touches = i2cdat[0x02];
|
||||
if ((touches > 2) || (touches == 0)) {
|
||||
touches = 0;
|
||||
}
|
||||
|
||||
#ifdef FT6206_DEBUG
|
||||
Serial.print("# Touches: ");
|
||||
Serial.println(touches);
|
||||
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
Serial.print("0x");
|
||||
Serial.print(i2cdat[i], HEX);
|
||||
Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
if (i2cdat[0x01] != 0x00) {
|
||||
Serial.print("Gesture #");
|
||||
Serial.println(i2cdat[0x01]);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
touchX[i] = i2cdat[0x03 + i * 6] & 0x0F;
|
||||
touchX[i] <<= 8;
|
||||
touchX[i] |= i2cdat[0x04 + i * 6];
|
||||
touchY[i] = i2cdat[0x05 + i * 6] & 0x0F;
|
||||
touchY[i] <<= 8;
|
||||
touchY[i] |= i2cdat[0x06 + i * 6];
|
||||
touchID[i] = i2cdat[0x05 + i * 6] >> 4;
|
||||
}
|
||||
|
||||
#ifdef FT6206_DEBUG
|
||||
Serial.println();
|
||||
for (uint8_t i = 0; i < touches; i++) {
|
||||
Serial.print("ID #");
|
||||
Serial.print(touchID[i]);
|
||||
Serial.print("\t(");
|
||||
Serial.print(touchX[i]);
|
||||
Serial.print(", ");
|
||||
Serial.print(touchY[i]);
|
||||
Serial.print(") ");
|
||||
}
|
||||
Serial.println();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t FT6206::readRegister8(uint8_t reg) {
|
||||
uint8_t x;
|
||||
// use i2c
|
||||
Wire.beginTransmission(FT62XX_ADDR);
|
||||
Wire.write((byte)reg);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom((byte)FT62XX_ADDR, (byte)1);
|
||||
x = Wire.read();
|
||||
|
||||
#ifdef I2C_DEBUG
|
||||
Serial.print("$");
|
||||
Serial.print(reg, HEX);
|
||||
Serial.print(": 0x");
|
||||
Serial.println(x, HEX);
|
||||
#endif
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
void FT6206::writeRegister8(uint8_t reg, uint8_t val) {
|
||||
// use i2c
|
||||
Wire.beginTransmission(FT62XX_ADDR);
|
||||
Wire.write((byte)reg);
|
||||
Wire.write((byte)val);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
// DONT DO THIS - REALLY - IT DOESNT WORK
|
||||
void FT6206::autoCalibrate(void) {
|
||||
writeRegister8(FT06_REG_MODE, FT6206_REG_FACTORYMODE);
|
||||
delay(100);
|
||||
//Serial.println("Calibrating...");
|
||||
writeRegister8(FT6206_REG_CALIBRATE, 4);
|
||||
delay(300);
|
||||
for (uint8_t i = 0; i < 100; i++) {
|
||||
uint8_t temp;
|
||||
temp = readRegister8(FT6206_REG_MODE);
|
||||
Serial.println(temp, HEX);
|
||||
//return to normal mode, calibration finish
|
||||
if (0x0 == ((temp & 0x70) >> 4))
|
||||
break;
|
||||
}
|
||||
delay(200);
|
||||
//Serial.println("Calibrated");
|
||||
delay(300);
|
||||
writeRegister8(FT6206_REG_MODE, FT6206_REG_FACTORYMODE);
|
||||
delay(100);
|
||||
writeRegister8(FT6206_REG_CALIBRATE, 5);
|
||||
delay(300);
|
||||
writeRegister8(FT6206_REG_MODE, FT6206_REG_WORKMODE);
|
||||
delay(300);
|
||||
}
|
||||
*/
|
||||
|
||||
/****************/
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Instantiates a new FT6206 class with x, y and z set to 0 by default
|
||||
*/
|
||||
/**************************************************************************/
|
||||
TS_Point::TS_Point(void) { x = y = z = 0; }
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Instantiates a new FT6206 class with x, y and z set by params.
|
||||
@param _x The X coordinate
|
||||
@param _y The Y coordinate
|
||||
@param _z The Z coordinate
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
TS_Point::TS_Point(int16_t _x, int16_t _y, int16_t _z) {
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Simple == comparator for two TS_Point objects
|
||||
@returns True if x, y and z are the same for both points, False otherwise.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool TS_Point::operator==(TS_Point p1) {
|
||||
return ((p1.x == x) && (p1.y == y) && (p1.z == z));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Simple != comparator for two TS_Point objects
|
||||
@returns False if x, y and z are the same for both points, True otherwise.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool TS_Point::operator!=(TS_Point p1) {
|
||||
return ((p1.x != x) || (p1.y != y) || (p1.z != z));
|
||||
}
|
||||
74
reflow_plate_fw/lib/ft6206_touch/ft6206_touch.h
Normal file
74
reflow_plate_fw/lib/ft6206_touch/ft6206_touch.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <Wire.h>
|
||||
|
||||
#define FT62XX_ADDR 0x38 //!< I2C address
|
||||
#define FT62XX_G_FT5201ID 0xA8 //!< FocalTech's panel ID
|
||||
#define FT62XX_REG_NUMTOUCHES 0x02 //!< Number of touch points
|
||||
|
||||
#define FT62XX_NUM_X 0x33 //!< Touch X position
|
||||
#define FT62XX_NUM_Y 0x34 //!< Touch Y position
|
||||
|
||||
#define FT62XX_REG_MODE 0x00 //!< Device mode, either WORKING or FACTORY
|
||||
#define FT62XX_REG_CALIBRATE 0x02 //!< Calibrate mode
|
||||
#define FT62XX_REG_WORKMODE 0x00 //!< Work mode
|
||||
#define FT62XX_REG_FACTORYMODE 0x40 //!< Factory mode
|
||||
#define FT62XX_REG_THRESHHOLD 0x80 //!< Threshold for touch detection
|
||||
#define FT62XX_REG_POINTRATE 0x88 //!< Point rate
|
||||
#define FT62XX_REG_FIRMVERS 0xA6 //!< Firmware version
|
||||
#define FT62XX_REG_CHIPID 0xA3 //!< Chip selecting
|
||||
#define FT62XX_REG_VENDID 0xA8 //!< FocalTech's panel ID
|
||||
|
||||
#define FT62XX_VENDID 0x11 //!< FocalTech's panel ID
|
||||
#define FT6206_CHIPID 0x06 //!< Chip selecting
|
||||
#define FT6236_CHIPID 0x36 //!< Chip selecting
|
||||
#define FT6236U_CHIPID 0x64 //!< Chip selecting
|
||||
|
||||
// calibrated for Adafruit 2.8" ctp screen
|
||||
#define FT62XX_DEFAULT_THRESHOLD 128 //!< Default threshold for touch detection
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Helper class that stores a TouchScreen Point with x, y, and z
|
||||
coordinates, for easy math/comparison
|
||||
*/
|
||||
/**************************************************************************/
|
||||
class TS_Point {
|
||||
public:
|
||||
TS_Point(void);
|
||||
TS_Point(int16_t x, int16_t y, int16_t z);
|
||||
|
||||
bool operator==(TS_Point);
|
||||
bool operator!=(TS_Point);
|
||||
|
||||
int16_t x; /*!< X coordinate */
|
||||
int16_t y; /*!< Y coordinate */
|
||||
int16_t z; /*!< Z coordinate (often used for pressure) */
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Class that stores state and functions for interacting with FT6206
|
||||
capacitive touch chips
|
||||
*/
|
||||
/**************************************************************************/
|
||||
class FT6206 {
|
||||
public:
|
||||
FT6206(void);
|
||||
bool begin(uint8_t sda, uint8_t scl, uint16_t width, uint16_t height, bool flip = false, uint8_t thresh = FT62XX_DEFAULT_THRESHOLD);
|
||||
uint8_t touched(void);
|
||||
TS_Point getPoint(uint8_t n = 0);
|
||||
|
||||
// void autoCalibrate(void);
|
||||
|
||||
private:
|
||||
uint16_t _width, _height;
|
||||
bool _flip;
|
||||
void writeRegister8(uint8_t reg, uint8_t val);
|
||||
uint8_t readRegister8(uint8_t reg);
|
||||
|
||||
void readData(void);
|
||||
uint8_t touches;
|
||||
uint16_t touchX[2], touchY[2], touchID[2];
|
||||
};
|
||||
@@ -14,12 +14,16 @@ board = blackpill_f411ce
|
||||
framework = arduino
|
||||
upload_protocol = stlink
|
||||
debug_tool = stlink
|
||||
monitor_speed = 115200
|
||||
monitor_port = /dev/cu.usbmodem3474359635391
|
||||
lib_deps =
|
||||
yuriisalimov/MAX6675_Thermocouple@^2.0.2
|
||||
bodmer/TFT_eSPI@^2.3.70
|
||||
br3ttb/PID@^1.2.1
|
||||
robtillaart/MAX31855@^0.2.5
|
||||
;adafruit/Adafruit FT6206 Library@^1.0.6
|
||||
lib_ldf_mode = deep+
|
||||
build_flags =
|
||||
build_flags =
|
||||
-D USER_SETUP_LOADED=1
|
||||
-include include/Setup202_SSD1351_128.h
|
||||
|
||||
|
||||
-include include/ILI9341_STM32.h
|
||||
-D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
|
||||
-D PIO_FRAMEWORK_ARDUINO_USB_FULLSPEED_FULLMODE
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#define LCD_MOSI PA7
|
||||
#define LCD_SCLK PA5
|
||||
#define LCD_RES PA12
|
||||
#define LCD_DC PB1
|
||||
#define LCD_CS PB0
|
||||
// #define LCD_MOSI PA7
|
||||
// #define LCD_SCLK PA5
|
||||
// #define LCD_RES PA8
|
||||
// #define LCD_DC PB1
|
||||
// #define LCD_CS PB0
|
||||
|
||||
#define THERM_CS PB4
|
||||
#define THERM_SO PB5
|
||||
#define THERM_CL PB6
|
||||
#define THERM_SS PB12
|
||||
#define THERM_MISO PB14
|
||||
#define THERM_CLK PB13
|
||||
#define THERM_MOSI PB15 //not used
|
||||
|
||||
#define BUt_LEFT PB15
|
||||
#define BUt_RIGHT PA10
|
||||
#define BUT_UP PA11
|
||||
#define BUT_DOWN PA9
|
||||
#define BUT_CENTER PA8
|
||||
|
||||
#define HEAT_OUT PA2
|
||||
#define HEAT_OUT PA2
|
||||
|
||||
#define BUZZER A4
|
||||
|
||||
#define BUTTON_SELECT 0
|
||||
#define BUTTON_AXIS_Y 0
|
||||
#define BUTTON_AXIS_X 0
|
||||
#define BUTTON_MENU 0
|
||||
#define BUTTON_BACK 0
|
||||
|
||||
@@ -1,10 +1,281 @@
|
||||
#include "button.h"
|
||||
|
||||
#include "controlloop.h"
|
||||
|
||||
#define DEBOUNCE_MS 100
|
||||
Button start_btn(0, false, DEBOUNCE_MS, true);
|
||||
Button stop_btn(0, false, DEBOUNCE_MS, true);
|
||||
Button set_btn(0, false, DEBOUNCE_MS, true);
|
||||
|
||||
Button *buttons[] = {&start_btn, &stop_btn, &set_btn};
|
||||
|
||||
void setButton(uint8_t index, bool state)
|
||||
{
|
||||
buttons[index]->setButton(state);
|
||||
}
|
||||
|
||||
void readAllButtons(void)
|
||||
{
|
||||
for (auto &&button : buttons)
|
||||
{
|
||||
button->read();
|
||||
}
|
||||
}
|
||||
|
||||
void initButton(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void handleButton(void)
|
||||
{
|
||||
|
||||
readAllButtons();
|
||||
|
||||
if (start_btn.isPressed())
|
||||
{
|
||||
setReflowStatus(true);
|
||||
}
|
||||
if (stop_btn.isPressed())
|
||||
{
|
||||
setReflowStatus(false);
|
||||
}
|
||||
if (set_btn.isPressed())
|
||||
{
|
||||
//enter menu
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Arduino Button Library v1.0 *
|
||||
* Jack Christensen May 2011, published Mar 2012 *
|
||||
* *
|
||||
* Library for reading momentary contact switches like tactile button *
|
||||
* switches. Intended for use in state machine constructs. *
|
||||
* Use the read() function to read all buttons in the main loop, *
|
||||
* which should execute as fast as possible. *
|
||||
* *
|
||||
* This work is licensed under the Creative Commons Attribution- *
|
||||
* ShareAlike 3.0 Unported License. To view a copy of this license, *
|
||||
* visit http://creativecommons.org/licenses/by-sa/3.0/ or send a *
|
||||
* letter to Creative Commons, 171 Second Street, Suite 300, *
|
||||
* San Francisco, California, 94105, USA. *
|
||||
*----------------------------------------------------------------------*/
|
||||
|
||||
#include "Button.h"
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Button(pin, puEnable, invert, dbTime) instantiates a button object. *
|
||||
* pin Is the Arduino pin the button is connected to. *
|
||||
* puEnable Enables the AVR internal pullup resistor if != 0 (can also *
|
||||
* use true or false). *
|
||||
* invert If invert == 0, interprets a high state as pressed, low as *
|
||||
* released. If invert != 0, interprets a high state as *
|
||||
* released, low as pressed (can also use true or false). *
|
||||
* dbTime Is the debounce time in milliseconds. *
|
||||
* *
|
||||
* (Note that invert cannot be implied from puEnable since an external *
|
||||
* pullup could be used.) *
|
||||
*----------------------------------------------------------------------*/
|
||||
Button::Button(uint8_t pin, uint8_t invert, uint32_t dbTime, bool isTouch) : _isTouchButton(isTouch)
|
||||
{
|
||||
if (!_isTouchButton)
|
||||
{
|
||||
_pin = pin;
|
||||
pinMode(_pin, INPUT_PULLUP);
|
||||
_state = digitalRead(_pin);
|
||||
}
|
||||
_invert = invert;
|
||||
_dbTime = dbTime;
|
||||
if (_invert != 0)
|
||||
_state = !_state;
|
||||
_time = millis();
|
||||
_lastState = _state;
|
||||
_changed = 0;
|
||||
_lastTime = _time;
|
||||
_lastChange = _time;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* read() returns the state of the button, 1==pressed, 0==released, *
|
||||
* does debouncing, captures and maintains times, previous states, etc. *
|
||||
*----------------------------------------------------------------------*/
|
||||
uint8_t Button::read(void)
|
||||
{
|
||||
static uint32_t ms;
|
||||
static uint8_t pinVal;
|
||||
|
||||
ms = millis();
|
||||
if (_isTouchButton)
|
||||
{
|
||||
pinVal = _touchState;
|
||||
}
|
||||
else
|
||||
{
|
||||
pinVal = digitalRead(_pin);
|
||||
}
|
||||
|
||||
if (_invert != 0)
|
||||
pinVal = !pinVal;
|
||||
if (ms - _lastChange < _dbTime)
|
||||
{
|
||||
_lastTime = _time;
|
||||
_time = ms;
|
||||
_changed = 0;
|
||||
return _state;
|
||||
Serial.println("State is: " + _state);
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastTime = _time;
|
||||
_lastState = _state;
|
||||
_state = pinVal;
|
||||
_time = ms;
|
||||
if (_state != _lastState)
|
||||
{
|
||||
_lastChange = ms;
|
||||
_changed = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_changed = 0;
|
||||
}
|
||||
return _state;
|
||||
#ifdef DEBUG
|
||||
Serial.println("State is: " + _state);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Button::setButton(bool state)
|
||||
{
|
||||
_touchState = state;
|
||||
}
|
||||
|
||||
uint8_t Button::readAxis()
|
||||
{
|
||||
static uint32_t ms;
|
||||
static uint8_t pinVal;
|
||||
static uint16_t val;
|
||||
|
||||
ms = millis();
|
||||
val = analogRead(_pin);
|
||||
|
||||
if (val > 3900)
|
||||
{
|
||||
pinVal = 1;
|
||||
_axis = DPAD_V_FULL;
|
||||
#ifdef DEBUG
|
||||
Serial.println("Value is: " + val);
|
||||
#endif
|
||||
}
|
||||
else if (val > 1500 && val < 2000)
|
||||
{
|
||||
pinVal = 1;
|
||||
_axis = DPAD_V_HALF;
|
||||
#ifdef DEBUG
|
||||
Serial.println("Value is: " + val);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
pinVal = 0;
|
||||
_axis = DPAD_V_NONE;
|
||||
}
|
||||
|
||||
if (_invert == 0)
|
||||
pinVal = !pinVal;
|
||||
if (ms - _lastChange < _dbTime)
|
||||
{
|
||||
_lastTime = _time;
|
||||
_time = ms;
|
||||
_changed = 0;
|
||||
return _state;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastTime = _time;
|
||||
_lastState = _state;
|
||||
_state = pinVal;
|
||||
_time = ms;
|
||||
if (_state != _lastState)
|
||||
{
|
||||
_lastChange = ms;
|
||||
_changed = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_changed = 0;
|
||||
}
|
||||
return _state;
|
||||
}
|
||||
return _state && _changed;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* isPressed() and isReleased() check the button state when it was last *
|
||||
* read, and return false (0) or true (!=0) accordingly. *
|
||||
* These functions do not cause the button to be read. *
|
||||
*----------------------------------------------------------------------*/
|
||||
uint8_t Button::isPressed(void)
|
||||
{
|
||||
return _state == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
uint8_t Button::isAxisPressed(void)
|
||||
{
|
||||
if (_state)
|
||||
return _axis;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t Button::isReleased(void)
|
||||
{
|
||||
return _state == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* wasPressed() and wasReleased() check the button state to see if it *
|
||||
* changed between the last two reads and return false (0) or *
|
||||
* true (!=0) accordingly. *
|
||||
* These functions do not cause the button to be read. *
|
||||
*----------------------------------------------------------------------*/
|
||||
uint8_t Button::wasPressed(void)
|
||||
{
|
||||
return _state && _changed;
|
||||
}
|
||||
|
||||
uint8_t Button::wasAxisPressed(void)
|
||||
{
|
||||
if (_state && _changed)
|
||||
return _axis;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t Button::wasReleased(void)
|
||||
{
|
||||
return !_state && _changed;
|
||||
}
|
||||
/*----------------------------------------------------------------------*
|
||||
* pressedFor(ms) and releasedFor(ms) check to see if the button is *
|
||||
* pressed (or released), and has been in that state for the specified *
|
||||
* time in milliseconds. Returns false (0) or true (1) accordingly. *
|
||||
* These functions do not cause the button to be read. *
|
||||
*----------------------------------------------------------------------*/
|
||||
uint8_t Button::pressedFor(uint32_t ms)
|
||||
{
|
||||
return (_state == 1 && _time - _lastChange >= ms) ? 1 : 0;
|
||||
}
|
||||
|
||||
uint8_t Button::releasedFor(uint32_t ms)
|
||||
{
|
||||
return (_state == 0 && _time - _lastChange >= ms) ? 1 : 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------*
|
||||
* lastChange() returns the time the button last changed state, *
|
||||
* in milliseconds. *
|
||||
*----------------------------------------------------------------------*/
|
||||
uint32_t Button::lastChange(void)
|
||||
{
|
||||
return _lastChange;
|
||||
}
|
||||
@@ -4,4 +4,64 @@
|
||||
#include "board.h"
|
||||
|
||||
void initButton(void);
|
||||
void handleButton(void);
|
||||
void handleButton(void);
|
||||
void setButton(uint8_t index, bool state);
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*
|
||||
* Arduino Button Library v1.0 *
|
||||
* Jack Christensen Mar 2012 *
|
||||
* *
|
||||
* This work is licensed under the Creative Commons Attribution- *
|
||||
* ShareAlike 3.0 Unported License. To view a copy of this license, *
|
||||
* visit http://creativecommons.org/licenses/by-sa/3.0/ or send a *
|
||||
* letter to Creative Commons, 171 Second Street, Suite 300, *
|
||||
* San Francisco, California, 94105, USA. *
|
||||
*----------------------------------------------------------------------*/
|
||||
#ifndef Button_h
|
||||
#define Button_h
|
||||
// #if ARDUINO >= 100
|
||||
#include <Arduino.h>
|
||||
// #else
|
||||
// #include <WProgram.h>
|
||||
// #endif
|
||||
|
||||
|
||||
#define DPAD_V_FULL 2
|
||||
#define DPAD_V_HALF 1
|
||||
#define DPAD_V_NONE 0
|
||||
|
||||
class Button
|
||||
{
|
||||
public:
|
||||
Button(uint8_t pin, uint8_t invert, uint32_t dbTime, bool isTouch);
|
||||
uint8_t read();
|
||||
uint8_t readAxis();
|
||||
uint8_t isPressed();
|
||||
uint8_t isAxisPressed();
|
||||
uint8_t isReleased();
|
||||
uint8_t wasPressed();
|
||||
uint8_t wasAxisPressed();
|
||||
uint8_t wasReleased();
|
||||
uint8_t pressedFor(uint32_t ms);
|
||||
uint8_t releasedFor(uint32_t ms);
|
||||
uint32_t lastChange();
|
||||
void setButton(bool state);
|
||||
|
||||
|
||||
private:
|
||||
uint8_t _pin; //arduino pin number
|
||||
uint8_t _puEnable; //internal pullup resistor enabled
|
||||
uint8_t _invert; //if 0, interpret high state as pressed, else interpret low state as pressed
|
||||
uint8_t _state; //current button state
|
||||
uint8_t _lastState; //previous button state
|
||||
uint8_t _changed; //state changed since last read
|
||||
uint8_t _axis; //state changed since last read
|
||||
uint32_t _time; //time of current state (all times are in ms)
|
||||
uint32_t _lastTime; //time of previous state
|
||||
uint32_t _lastChange; //time of last state change
|
||||
uint32_t _dbTime; //debounce time
|
||||
const bool _isTouchButton;
|
||||
bool _touchState;
|
||||
};
|
||||
#endif
|
||||
589
reflow_plate_fw/src/controlloop.cpp
Normal file
589
reflow_plate_fw/src/controlloop.cpp
Normal file
@@ -0,0 +1,589 @@
|
||||
#include "controlloop.h"
|
||||
|
||||
#include "thermo.h"
|
||||
#include "button.h"
|
||||
#include "lcd.h"
|
||||
|
||||
// Button AXIS_Y = Button(BUTTON_AXIS_Y, true, DEBOUNCE_MS);
|
||||
// Button AXIS_X = Button(BUTTON_AXIS_X, true, DEBOUNCE_MS);
|
||||
|
||||
/*******************************************************************************
|
||||
Title: Reflow Oven Controller
|
||||
Version: 1.20
|
||||
Date: 26-11-2012
|
||||
Company: Rocket Scream Electronics
|
||||
Author: Lim Phang Moh
|
||||
Website: www.rocketscream.com
|
||||
|
||||
Brief
|
||||
=====
|
||||
This is an example firmware for our Arduino compatible reflow oven controller.
|
||||
The reflow curve used in this firmware is meant for lead-free profile
|
||||
(it's even easier for leaded process!). You'll need to use the MAX31855
|
||||
library for Arduino if you are having a shield of v1.60 & above which can be
|
||||
downloaded from our GitHub repository. Please check our wiki
|
||||
(www.rocketscream.com/wiki) for more information on using this piece of code
|
||||
together with the reflow oven controller shield.
|
||||
|
||||
Temperature (Degree Celcius) Magic Happens Here!
|
||||
245-| x x
|
||||
| x x
|
||||
| x x
|
||||
| x x
|
||||
200-| x x
|
||||
| x | | x
|
||||
| x | | x
|
||||
| x | |
|
||||
150-| x | |
|
||||
| x | | |
|
||||
| x | | |
|
||||
| x | | |
|
||||
| x | | |
|
||||
| x | | |
|
||||
| x | | |
|
||||
30 -| x | | |
|
||||
|< 60 - 90 s >|< 90 - 120 s >|< 90 - 120 s >|
|
||||
| Preheat Stage | Soaking Stage | Reflow Stage | Cool
|
||||
0 |_ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
Time (Seconds)
|
||||
|
||||
This firmware owed very much on the works of other talented individuals as
|
||||
follows:
|
||||
==========================================
|
||||
Brett Beauregard (www.brettbeauregard.com)
|
||||
==========================================
|
||||
Author of Arduino PID library. On top of providing industry standard PID
|
||||
implementation, he gave a lot of help in making this reflow oven controller
|
||||
possible using his awesome library.
|
||||
|
||||
==========================================
|
||||
Limor Fried of Adafruit (www.adafruit.com)
|
||||
==========================================
|
||||
Author of Arduino MAX6675 library. Adafruit has been the source of tonnes of
|
||||
tutorials, examples, and libraries for everyone to learn.
|
||||
|
||||
Disclaimer
|
||||
==========
|
||||
Dealing with high voltage is a very dangerous act! Please make sure you know
|
||||
what you are dealing with and have proper knowledge before hand. Your use of
|
||||
any information or materials on this reflow oven controller is entirely at
|
||||
your own risk, for which we shall not be liable.
|
||||
|
||||
Licences
|
||||
========
|
||||
This reflow oven controller hardware and firmware are released under the
|
||||
Creative Commons Share Alike v3.0 license
|
||||
http://creativecommons.org/licenses/by-sa/3.0/
|
||||
You are free to take this piece of code, use it and modify it.
|
||||
All we ask is attribution including the supporting libraries used in this
|
||||
firmware.
|
||||
|
||||
Required Libraries
|
||||
==================
|
||||
- Arduino PID Library:
|
||||
>> https://github.com/br3ttb/Arduino-PID-Library
|
||||
- MAX31855 Library (for board v1.60 & above):
|
||||
>> https://github.com/rocketscream/MAX31855
|
||||
- MAX6675 Library (for board v1.50 & below):
|
||||
>> https://github.com/adafruit/MAX6675-library
|
||||
|
||||
Revision Description
|
||||
======== ===========
|
||||
1.20 Adds supports for v1.60 (and above) of Reflow Oven Controller
|
||||
Shield:
|
||||
- Uses MAX31855KASA+ chip and pin reassign (allowing A4 & A5 (I2C)
|
||||
to be used for user application).
|
||||
- Uses analog based switch (allowing D2 & D3 to be used for user
|
||||
application).
|
||||
Adds waiting state when temperature too hot to start reflow process.
|
||||
Corrected thermocouple disconnect error interpretation (MAX6675).
|
||||
1.10 Arduino IDE 1.0 compatible.
|
||||
1.00 Initial public release.
|
||||
*******************************************************************************/
|
||||
// Comment either one the following #define to select your board revision
|
||||
// Newer board version starts from v1.60 using MAX31855KASA+ chip
|
||||
|
||||
// ***** LCD MESSAGES *****
|
||||
const char *lcdMessagesReflowStatus[] = {
|
||||
"Ready",
|
||||
"Preheat",
|
||||
"Soaking",
|
||||
"Reflow",
|
||||
"Cooling",
|
||||
"Done",
|
||||
"Warning, HOT!",
|
||||
"Error"};
|
||||
|
||||
// ***** DEGREE SYMBOL FOR LCD *****
|
||||
unsigned char degree[8] = {
|
||||
140, 146, 146, 140, 128, 128, 128, 128};
|
||||
|
||||
// ***** PID CONTROL VARIABLES *****
|
||||
double setpoint;
|
||||
double input;
|
||||
double output;
|
||||
double kp = PID_KP_PREHEAT;
|
||||
double ki = PID_KI_PREHEAT;
|
||||
double kd = PID_KD_PREHEAT;
|
||||
int windowSize;
|
||||
int inputInt;
|
||||
unsigned long windowStartTime;
|
||||
unsigned long nextCheck;
|
||||
unsigned long nextRead;
|
||||
unsigned long timerSoak;
|
||||
unsigned long buzzerPeriod;
|
||||
// Reflow oven controller state machine state variable
|
||||
reflowState_t reflowState;
|
||||
// Reflow oven controller status
|
||||
reflowStatus_t reflowStatus;
|
||||
// Switch debounce state machine state variable
|
||||
debounceState_t debounceState;
|
||||
// Switch debounce timer
|
||||
long lastDebounceTime;
|
||||
// Switch press status
|
||||
switch_t switchStatus;
|
||||
// Seconds timer
|
||||
int timerSeconds;
|
||||
//output state
|
||||
bool outputState = false;
|
||||
|
||||
bool isFault;
|
||||
String activeStatus;
|
||||
int oldTemp = 0;
|
||||
byte state;
|
||||
bool disableMenu;
|
||||
bool profileIsOn;
|
||||
uint32_t processStartTime = 0;
|
||||
|
||||
// Specify PID control interface & it must be here, after all declaration
|
||||
PID reflowOvenPID(&input, &output, &setpoint, kp, ki, kd, DIRECT);
|
||||
|
||||
void initControlLoop(void)
|
||||
{
|
||||
// Set window size
|
||||
windowSize = 2000;
|
||||
// Initialize time keeping variable
|
||||
nextCheck = millis();
|
||||
// Initialize thermocouple reading variable
|
||||
nextRead = millis();
|
||||
|
||||
pinMode(HEAT_OUT, OUTPUT);
|
||||
}
|
||||
|
||||
String getReflowStatus_str(void)
|
||||
{
|
||||
switch (reflowStatus)
|
||||
{
|
||||
case REFLOW_STATUS_OFF:
|
||||
{
|
||||
return String("Reflow OFF");
|
||||
}
|
||||
break;
|
||||
case REFLOW_STATUS_ON:
|
||||
{
|
||||
return String("Reflow ON");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
return String("Unknow State");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String getReflowState_str(void)
|
||||
{
|
||||
switch (reflowState)
|
||||
{
|
||||
case REFLOW_STATE_IDLE:
|
||||
return String("Idle");
|
||||
break;
|
||||
case REFLOW_STATE_PREHEAT:
|
||||
return String("Preheating");
|
||||
break;
|
||||
case REFLOW_STATE_SOAK:
|
||||
return String("Soaking");
|
||||
break;
|
||||
case REFLOW_STATE_REFLOW:
|
||||
return String("Reflowing");
|
||||
break;
|
||||
case REFLOW_STATE_COOL:
|
||||
return String("Cooling");
|
||||
break;
|
||||
case REFLOW_STATE_COMPLETE:
|
||||
return String("Completed");
|
||||
break;
|
||||
case REFLOW_STATE_TOO_HOT:
|
||||
return String("HOT!");
|
||||
break;
|
||||
case REFLOW_STATE_ERROR:
|
||||
return String("Error");
|
||||
break;
|
||||
default:
|
||||
return String("Unknow State");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setReflowStatus(bool newStatus)
|
||||
{
|
||||
if (newStatus)
|
||||
{
|
||||
profileIsOn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
profileIsOn = false;
|
||||
reflowStatus = REFLOW_STATUS_OFF;
|
||||
// Reinitialize state machine
|
||||
reflowState = REFLOW_STATE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
reflowStatus_t getReflowStatus(void)
|
||||
{
|
||||
return reflowStatus;
|
||||
}
|
||||
|
||||
double getReflowTargetTemp(void)
|
||||
{
|
||||
return setpoint;
|
||||
}
|
||||
|
||||
bool getOutputState(void)
|
||||
{
|
||||
return outputState;
|
||||
}
|
||||
|
||||
uint32_t safetyTimer = 0;
|
||||
#define SAFETYTIMEOUT 5000 //ms
|
||||
double oldinput = 0;
|
||||
#define SAFETYMARGIN 5 //degrees C
|
||||
bool SafetyError = false;
|
||||
|
||||
bool getSafetyCheck(void)
|
||||
{
|
||||
uint32_t timeNow = millis();
|
||||
if (!outputState)
|
||||
{
|
||||
safetyTimer = timeNow;
|
||||
oldinput = input;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (timeNow - safetyTimer > SAFETYTIMEOUT)
|
||||
{
|
||||
if (input - oldinput < SAFETYMARGIN)
|
||||
{
|
||||
setReflowStatus(false);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
oldinput = input;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
float getProcessTime(void)
|
||||
{
|
||||
if ((reflowStatus == REFLOW_STATUS_ON) && (processStartTime > 0))
|
||||
{
|
||||
float retval = (millis() - processStartTime);
|
||||
retval /= 1000;
|
||||
return retval;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool getOverheating(void)
|
||||
{
|
||||
return (reflowState == REFLOW_STATE_TOO_HOT);
|
||||
}
|
||||
|
||||
void handleReflowStatemachine(void)
|
||||
{
|
||||
// Reflow oven controller state machine
|
||||
switch (reflowState)
|
||||
{
|
||||
case REFLOW_STATE_IDLE:
|
||||
activeStatus = "Idle";
|
||||
processStartTime = 0;
|
||||
// If oven temperature is still above room temperature
|
||||
if (input >= TEMPERATURE_ROOM)
|
||||
{
|
||||
reflowState = REFLOW_STATE_TOO_HOT;
|
||||
Serial.println("Status: Too hot to start");
|
||||
}
|
||||
else
|
||||
{
|
||||
// If switch is pressed to start reflow process
|
||||
//if (switchStatus == SWITCH_1)
|
||||
if (profileIsOn != 0)
|
||||
{
|
||||
// Send header for CSV file
|
||||
Serial.println("Time Setpoint Input Output");
|
||||
// Intialize seconds timer for serial debug information
|
||||
timerSeconds = 0;
|
||||
// Initialize PID control window starting time
|
||||
windowStartTime = millis();
|
||||
// Ramp up to minimum soaking temperature
|
||||
setpoint = TEMPERATURE_SOAK_MIN + 5;
|
||||
// Tell the PID to range between 0 and the full window size
|
||||
reflowOvenPID.SetOutputLimits(0, windowSize);
|
||||
reflowOvenPID.SetSampleTime(PID_SAMPLE_TIME);
|
||||
// Turn the PID on
|
||||
reflowOvenPID.SetMode(AUTOMATIC);
|
||||
// Proceed to preheat stage
|
||||
reflowState = REFLOW_STATE_PREHEAT;
|
||||
// log process start time
|
||||
processStartTime = millis();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case REFLOW_STATE_PREHEAT:
|
||||
activeStatus = "Preheat";
|
||||
reflowStatus = REFLOW_STATUS_ON;
|
||||
// If minimum soak temperature is achieve
|
||||
if (input >= TEMPERATURE_SOAK_MIN)
|
||||
{
|
||||
// Chop soaking period into smaller sub-period
|
||||
timerSoak = millis() + SOAK_MICRO_PERIOD;
|
||||
// Set less agressive PID parameters for soaking ramp
|
||||
reflowOvenPID.SetTunings(PID_KP_SOAK, PID_KI_SOAK, PID_KD_SOAK);
|
||||
// Ramp up to first section of soaking temperature
|
||||
setpoint = TEMPERATURE_SOAK_MIN + SOAK_TEMPERATURE_STEP;
|
||||
// Proceed to soaking state
|
||||
reflowState = REFLOW_STATE_SOAK;
|
||||
}
|
||||
break;
|
||||
|
||||
case REFLOW_STATE_SOAK:
|
||||
activeStatus = "Soak";
|
||||
// If micro soak temperature is achieved
|
||||
if (millis() > timerSoak)
|
||||
{
|
||||
timerSoak = millis() + SOAK_MICRO_PERIOD;
|
||||
// Increment micro setpoint
|
||||
setpoint += SOAK_TEMPERATURE_STEP;
|
||||
if (setpoint > TEMPERATURE_SOAK_MAX)
|
||||
{
|
||||
// Set agressive PID parameters for reflow ramp
|
||||
reflowOvenPID.SetTunings(PID_KP_REFLOW, PID_KI_REFLOW, PID_KD_REFLOW);
|
||||
// Ramp up to first section of soaking temperature
|
||||
setpoint = TEMPERATURE_REFLOW_MAX;
|
||||
// Proceed to reflowing state
|
||||
reflowState = REFLOW_STATE_REFLOW;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case REFLOW_STATE_REFLOW:
|
||||
activeStatus = "Reflow";
|
||||
// We need to avoid hovering at peak temperature for too long
|
||||
// Crude method that works like a charm and safe for the components
|
||||
if (input >= (TEMPERATURE_REFLOW_MAX - 5))
|
||||
{
|
||||
// Set PID parameters for cooling ramp
|
||||
reflowOvenPID.SetTunings(PID_KP_REFLOW, PID_KI_REFLOW, PID_KD_REFLOW);
|
||||
// Ramp down to minimum cooling temperature
|
||||
setpoint = TEMPERATURE_COOL_MIN;
|
||||
// Proceed to cooling state
|
||||
reflowState = REFLOW_STATE_COOL;
|
||||
}
|
||||
break;
|
||||
|
||||
case REFLOW_STATE_COOL:
|
||||
activeStatus = "Cool";
|
||||
// If minimum cool temperature is achieve
|
||||
if (input <= TEMPERATURE_COOL_MIN)
|
||||
{
|
||||
// Retrieve current time for buzzer usage
|
||||
buzzerPeriod = millis() + 1000;
|
||||
// Turn on buzzer and green LED to indicate completion
|
||||
digitalWrite(BUZZER, HIGH);
|
||||
// Turn off reflow process
|
||||
reflowStatus = REFLOW_STATUS_OFF;
|
||||
// Proceed to reflow Completion state
|
||||
reflowState = REFLOW_STATE_COMPLETE;
|
||||
}
|
||||
break;
|
||||
|
||||
case REFLOW_STATE_COMPLETE:
|
||||
activeStatus = "Complete";
|
||||
if (millis() > buzzerPeriod)
|
||||
{
|
||||
// Turn off buzzer and green LED
|
||||
digitalWrite(BUZZER, LOW);
|
||||
// Reflow process ended
|
||||
reflowState = REFLOW_STATE_IDLE;
|
||||
profileIsOn = 0;
|
||||
Serial.println("Profile is OFF");
|
||||
}
|
||||
break;
|
||||
|
||||
case REFLOW_STATE_TOO_HOT:
|
||||
// If oven temperature drops below room temperature
|
||||
if (input < TEMPERATURE_ROOM)
|
||||
{
|
||||
// Ready to reflow
|
||||
reflowState = REFLOW_STATE_IDLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case REFLOW_STATE_ERROR:
|
||||
// If thermocouple problem is still present
|
||||
|
||||
if (input == 0) // || (input == FAULT_SHORT_GND) ||
|
||||
// (input == FAULT_SHORT_VCC))
|
||||
{
|
||||
// Wait until thermocouple wire is connected
|
||||
reflowState = REFLOW_STATE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clear to perform reflow process
|
||||
reflowState = REFLOW_STATE_IDLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void handleReflowPID(void)
|
||||
{
|
||||
unsigned long now;
|
||||
// PID computation and SSR control
|
||||
if (reflowStatus == REFLOW_STATUS_ON)
|
||||
{
|
||||
now = millis();
|
||||
|
||||
reflowOvenPID.Compute();
|
||||
|
||||
if ((now - windowStartTime) > windowSize)
|
||||
{
|
||||
// Time to shift the Relay Window
|
||||
windowStartTime += windowSize;
|
||||
}
|
||||
if (output > (now - windowStartTime))
|
||||
{
|
||||
digitalWrite(HEAT_OUT, HIGH);
|
||||
outputState = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
digitalWrite(HEAT_OUT, LOW);
|
||||
outputState = false;
|
||||
}
|
||||
}
|
||||
// Reflow oven process is off, ensure oven is off
|
||||
else
|
||||
{
|
||||
digitalWrite(HEAT_OUT, LOW);
|
||||
outputState = false;
|
||||
}
|
||||
}
|
||||
|
||||
void handleTemperatureReadings(void)
|
||||
{
|
||||
unsigned long now;
|
||||
|
||||
// Time to read thermocouple?
|
||||
if (millis() > nextRead)
|
||||
{
|
||||
|
||||
// Read thermocouple next sampling period
|
||||
nextRead += SENSOR_SAMPLING_TIME;
|
||||
// Read current temperature
|
||||
|
||||
input = getTemperature();
|
||||
// Check and print any faults
|
||||
uint8_t fault = getThermoCoupleFault();
|
||||
// inputInt = (int) input;
|
||||
// if ((input <= inputInt) || (input >= inputInt)) {
|
||||
// loopScreen();
|
||||
// }
|
||||
if ((((int)input) < inputInt) || (((int)input) > inputInt))
|
||||
{
|
||||
//loopScreen();
|
||||
}
|
||||
inputInt = input / 1;
|
||||
|
||||
if (oldTemp != inputInt)
|
||||
{
|
||||
if (state == 0)
|
||||
{
|
||||
loopScreen();
|
||||
}
|
||||
#ifdef Serial
|
||||
if ((input > 0) && (input <= 500))
|
||||
{
|
||||
Serial.print("Float temp: " + String(input));
|
||||
Serial.print(" ; ");
|
||||
Serial.println("Integer temp: " + String(inputInt));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// If thermocouple problem detected
|
||||
if (input == 0)
|
||||
{
|
||||
// Illegal operation
|
||||
reflowState = REFLOW_STATE_ERROR;
|
||||
reflowStatus = REFLOW_STATUS_OFF;
|
||||
}
|
||||
oldTemp = inputInt;
|
||||
}
|
||||
|
||||
if (millis() > nextCheck)
|
||||
{
|
||||
// Check input in the next seconds
|
||||
nextCheck += 1000;
|
||||
// If reflow process is on going
|
||||
if (reflowStatus == REFLOW_STATUS_ON)
|
||||
{
|
||||
// Increase seconds timer for reflow curve analysis
|
||||
timerSeconds++;
|
||||
// Send temperature and time stamp to serial
|
||||
Serial.print(timerSeconds);
|
||||
Serial.print(" ");
|
||||
Serial.print(setpoint);
|
||||
Serial.print(" ");
|
||||
Serial.print(input);
|
||||
Serial.print(" ");
|
||||
Serial.println(output);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Turn off red LED
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
}
|
||||
// If currently in error state
|
||||
if (reflowState == REFLOW_STATE_ERROR)
|
||||
{
|
||||
// No thermocouple wire connected
|
||||
Serial.println("TC Error!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- REFLOW MAIN LOOP ---- */
|
||||
void handleControlLoop()
|
||||
{
|
||||
if (state == 9)
|
||||
{
|
||||
Serial.println("handlecontrolloop: ERROR state");
|
||||
return;
|
||||
}
|
||||
//getSafetyCheck();
|
||||
handleTemperatureReadings();
|
||||
handleReflowStatemachine();
|
||||
handleReflowPID();
|
||||
}
|
||||
79
reflow_plate_fw/src/controlloop.h
Normal file
79
reflow_plate_fw/src/controlloop.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
#include <PID_v1.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
// ***** CONSTANTS *****
|
||||
#define TEMPERATURE_ROOM 75
|
||||
#define SENSOR_SAMPLING_TIME 1000
|
||||
#define DEBOUNCE_PERIOD_MIN 50
|
||||
|
||||
// ***** PARAMETERS *****
|
||||
// ***** PRE-HEAT STAGE *****
|
||||
#define PID_KP_PREHEAT 100
|
||||
#define PID_KI_PREHEAT 0.025
|
||||
#define PID_KD_PREHEAT 20
|
||||
#define PREHEAT_PERIOD 20000
|
||||
// ***** SOAKING STAGE *****
|
||||
#define PID_KP_SOAK 300
|
||||
#define PID_KI_SOAK 0.05
|
||||
#define PID_KD_SOAK 250
|
||||
#define TEMPERATURE_SOAK_MIN 150
|
||||
#define TEMPERATURE_SOAK_MAX 185
|
||||
#define SOAK_TEMPERATURE_STEP 5
|
||||
#define SOAK_MICRO_PERIOD 9000
|
||||
// ***** REFLOW STAGE *****
|
||||
#define PID_KP_REFLOW 300
|
||||
#define PID_KI_REFLOW 0.05
|
||||
#define PID_KD_REFLOW 350
|
||||
#define TEMPERATURE_REFLOW_MAX 220
|
||||
#define REFLOW_PERIOD 30000
|
||||
// ***** COOLING STAGE *****
|
||||
#define COOLDOWN_PERIOD 180000
|
||||
#define TEMPERATURE_COOL_MIN 100
|
||||
//PID settings
|
||||
#define PID_SAMPLE_TIME 1000
|
||||
|
||||
// ***** TYPE DEFINITIONS *****
|
||||
typedef enum REFLOW_STATE
|
||||
{
|
||||
REFLOW_STATE_IDLE,
|
||||
REFLOW_STATE_PREHEAT,
|
||||
REFLOW_STATE_SOAK,
|
||||
REFLOW_STATE_REFLOW,
|
||||
REFLOW_STATE_COOL,
|
||||
REFLOW_STATE_COMPLETE,
|
||||
REFLOW_STATE_TOO_HOT,
|
||||
REFLOW_STATE_ERROR
|
||||
} reflowState_t;
|
||||
|
||||
typedef enum REFLOW_STATUS
|
||||
{
|
||||
REFLOW_STATUS_OFF,
|
||||
REFLOW_STATUS_ON
|
||||
} reflowStatus_t;
|
||||
|
||||
typedef enum SWITCH
|
||||
{
|
||||
SWITCH_NONE,
|
||||
SWITCH_1,
|
||||
SWITCH_2
|
||||
} switch_t;
|
||||
|
||||
typedef enum DEBOUNCE_STATE
|
||||
{
|
||||
DEBOUNCE_STATE_IDLE,
|
||||
DEBOUNCE_STATE_CHECK,
|
||||
DEBOUNCE_STATE_RELEASE
|
||||
} debounceState_t;
|
||||
|
||||
void initControlLoop(void);
|
||||
void handleControlLoop(void);
|
||||
|
||||
String getReflowStatus_str(void);
|
||||
String getReflowState_str(void);
|
||||
reflowStatus_t getReflowStatus(void);
|
||||
void setReflowStatus(bool newStatus);
|
||||
double getReflowTargetTemp(void);
|
||||
bool getOutputState(void);
|
||||
float getProcessTime(void);
|
||||
bool getOverheating(void);
|
||||
@@ -1,12 +0,0 @@
|
||||
#include "heater.h"
|
||||
|
||||
|
||||
void initHeater(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void handleHeater(void)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "board.h"
|
||||
|
||||
void initHeater(void);
|
||||
void handleHeater(void);
|
||||
@@ -1,42 +1,417 @@
|
||||
#include "lcd.h"
|
||||
|
||||
#include "thermo.h"
|
||||
#include "controlloop.h"
|
||||
#include "button.h"
|
||||
#include <vector>
|
||||
|
||||
#include <TFT_eSPI.h> // Include the graphics library
|
||||
#include "ft6206_touch.h"
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(); // Create object "tft"
|
||||
FT6206 ts = FT6206();
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(); // Create object "tft"
|
||||
TFT_eSprite looptime_spr = TFT_eSprite(&tft);
|
||||
|
||||
//chart data
|
||||
TFT_eSprite chartXaxis_spr = TFT_eSprite(&tft);
|
||||
TFT_eSprite chartYaxis_spr = TFT_eSprite(&tft);
|
||||
TFT_eSprite chartArea_spr = TFT_eSprite(&tft);
|
||||
TFT_eSprite reflowstate_spr = TFT_eSprite(&tft);
|
||||
TFT_eSprite output_spr = TFT_eSprite(&tft);
|
||||
|
||||
//buttons
|
||||
String buttonNames[] = {"START", "STOP", "SET"};
|
||||
char buttonlabels[BUTTONS_N][10] = {"", "", ""};
|
||||
TFT_eSPI_Button key[BUTTONS_N];
|
||||
uint16_t calData[5] = {549, 3080, 343, 3159, 4};
|
||||
|
||||
uint32_t lastButtonTime = 0;
|
||||
|
||||
void updateTemperature(void)
|
||||
{
|
||||
//draw actualTemperature
|
||||
chartArea_spr.fillRoundRect(TEMP_X, 0, 60 - TEMP_R, TEMP_H, TEMP_R, TEMP_BG_COLOR);
|
||||
chartArea_spr.drawString("A:", TEMP_X + TEMP_LABEL_X, TEMP_H / 4);
|
||||
chartArea_spr.drawString("T:", TEMP_X + TEMP_LABEL_X, TEMP_H / 4 * 3);
|
||||
|
||||
chartArea_spr.drawFloat(getTemperature(), 1, TEMP_X + TEMP_VALUE_X, TEMP_H / 4);
|
||||
if (getReflowStatus() == REFLOW_STATUS_OFF)
|
||||
{
|
||||
chartArea_spr.drawString("--", TEMP_X + TEMP_VALUE_X, TEMP_H / 4 * 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
chartArea_spr.drawNumber(getReflowTargetTemp(), TEMP_X + TEMP_VALUE_X, TEMP_H / 4 * 3);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t calcTemp(double temp)
|
||||
{
|
||||
//map(long x, long in_min, long in_max, long out_min, long out_max)
|
||||
return CHART_H - map(temp, CHART_TEMP_MIN, CHART_TEMP_MAX, CHART_X_AXIS_OFFSET, CHART_H) + CHART_X_AXIS_OFFSET;
|
||||
}
|
||||
|
||||
uint32_t calcTempY(uint32_t inputY)
|
||||
{
|
||||
return map(inputY, CHART_H, CHART_X_AXIS_OFFSET, CHART_TEMP_MIN, CHART_TEMP_MAX);
|
||||
}
|
||||
|
||||
uint32_t calcTime(uint32_t timeMs)
|
||||
{
|
||||
return map((timeMs / 1000), 0, CHART_TIME_MAX, 0, CHART_W - CHART_Y_AXIS_OFFSET);
|
||||
}
|
||||
|
||||
std::vector<float> temperatureReading;
|
||||
uint32_t lastReading = 0;
|
||||
#define TEMPINTERVAL 1000
|
||||
|
||||
void updateRealtimeGraph(void)
|
||||
{
|
||||
if (getReflowStatus() == REFLOW_STATUS_OFF)
|
||||
{
|
||||
temperatureReading.clear();
|
||||
return;
|
||||
}
|
||||
//record temperature
|
||||
uint32_t timeNow = millis();
|
||||
if (timeNow - lastReading > TEMPINTERVAL)
|
||||
{
|
||||
temperatureReading.push_back(getTemperature());
|
||||
lastReading = timeNow;
|
||||
}
|
||||
|
||||
//draw graph
|
||||
uint32_t timeIndex = 0;
|
||||
uint32_t lastX = 0;
|
||||
uint32_t lastY = 0;
|
||||
for (auto &&sample : temperatureReading)
|
||||
{
|
||||
uint32_t nowX = calcTime(timeIndex * TEMPINTERVAL);
|
||||
uint32_t nowY = calcTemp(sample);
|
||||
chartArea_spr.drawLine(lastX, lastY, nowX, nowY, CHART_ACTUAL_COLOR);
|
||||
lastX = nowX;
|
||||
lastY = nowY;
|
||||
timeIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
void updateTargetChart(void)
|
||||
{
|
||||
|
||||
chartArea_spr.fillSprite(CHART_BG_COLOR);
|
||||
|
||||
//draw preheat
|
||||
uint32_t stepTimeStart = 0;
|
||||
uint32_t stepTimeStop = calcTime(PREHEAT_PERIOD);
|
||||
chartArea_spr.drawLine(stepTimeStart,
|
||||
CHART_H - CHART_X_AXIS_OFFSET,
|
||||
stepTimeStop,
|
||||
calcTemp(TEMPERATURE_SOAK_MIN),
|
||||
CHART_TARGET_COLOR);
|
||||
//draw soak
|
||||
stepTimeStart = stepTimeStop;
|
||||
stepTimeStop += calcTime(SOAK_MICRO_PERIOD * (((TEMPERATURE_SOAK_MAX - TEMPERATURE_SOAK_MIN) / SOAK_TEMPERATURE_STEP) - 1));
|
||||
chartArea_spr.drawLine(stepTimeStart,
|
||||
calcTemp(TEMPERATURE_SOAK_MIN),
|
||||
stepTimeStop,
|
||||
calcTemp(TEMPERATURE_SOAK_MAX),
|
||||
CHART_TARGET_COLOR);
|
||||
|
||||
//draw reflow
|
||||
stepTimeStart = stepTimeStop;
|
||||
stepTimeStop += calcTime(REFLOW_PERIOD);
|
||||
chartArea_spr.drawLine(stepTimeStart,
|
||||
calcTemp(TEMPERATURE_SOAK_MAX),
|
||||
stepTimeStop,
|
||||
calcTemp(TEMPERATURE_REFLOW_MAX),
|
||||
CHART_TARGET_COLOR);
|
||||
|
||||
//draw cool
|
||||
stepTimeStart = stepTimeStop;
|
||||
stepTimeStop += calcTime(COOLDOWN_PERIOD);
|
||||
chartArea_spr.drawLine(stepTimeStart,
|
||||
calcTemp(TEMPERATURE_REFLOW_MAX),
|
||||
stepTimeStop,
|
||||
calcTemp(TEMPERATURE_ROOM),
|
||||
CHART_TARGET_COLOR);
|
||||
|
||||
updateRealtimeGraph();
|
||||
|
||||
updateTemperature();
|
||||
chartArea_spr.pushSprite(CHART_X + CHART_Y_AXIS_OFFSET, CHART_Y);
|
||||
}
|
||||
|
||||
void prepTargetChart(void)
|
||||
{
|
||||
chartArea_spr.createSprite(CHART_W - CHART_Y_AXIS_OFFSET, CHART_H - CHART_X_AXIS_OFFSET);
|
||||
chartArea_spr.setTextFont(TEMP_FONT);
|
||||
chartArea_spr.setTextColor(TEMP_F_COLOR);
|
||||
chartArea_spr.setTextDatum(CL_DATUM);
|
||||
updateTargetChart();
|
||||
}
|
||||
|
||||
void updateReflowState(void)
|
||||
{
|
||||
uint32_t statusColor = STATE_BG_COLOR;
|
||||
if (getOverheating())
|
||||
{
|
||||
statusColor = TFT_RED;
|
||||
}
|
||||
reflowstate_spr.fillRoundRect(STATE_OFFSET, 0, (STATE_W / 2) - (2 * STATE_OFFSET), STATE_H, STATE_R, statusColor);
|
||||
reflowstate_spr.fillRoundRect(STATE_W / 2 + STATE_OFFSET, 0, (STATE_W / 2) - (2 * STATE_OFFSET), STATE_H, STATE_R, STATE_BG_COLOR);
|
||||
reflowstate_spr.drawString(getReflowState_str(), STATE_W / 4, STATE_H / 2);
|
||||
reflowstate_spr.drawString(getReflowStatus_str(), STATE_W / 4 * 3, STATE_H / 2);
|
||||
reflowstate_spr.pushSprite(STATE_X, STATE_Y);
|
||||
}
|
||||
|
||||
void prepReflowstate(void)
|
||||
{
|
||||
reflowstate_spr.createSprite(STATE_W, STATE_H);
|
||||
reflowstate_spr.setTextFont(STATE_FONT);
|
||||
reflowstate_spr.setTextColor(STATE_F_COLOR);
|
||||
reflowstate_spr.setTextDatum(MC_DATUM);
|
||||
updateReflowState();
|
||||
}
|
||||
|
||||
void updateOutput(void)
|
||||
{
|
||||
output_spr.fillSprite(OUTPUT_BG);
|
||||
if (getOutputState())
|
||||
{
|
||||
output_spr.fillCircle(OUTPUT_W / 2, OUTPUT_H / 2, OUTPUT_R, OUTPUT_ON_COLOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
output_spr.drawCircle(OUTPUT_W / 2, OUTPUT_H / 2, OUTPUT_R, OUTPUT_OFF_COLOR);
|
||||
}
|
||||
output_spr.pushSprite(OUTPUT_X, OUTPUT_Y);
|
||||
}
|
||||
|
||||
void prepOutput(void)
|
||||
{
|
||||
output_spr.createSprite(OUTPUT_W, OUTPUT_H);
|
||||
updateOutput();
|
||||
}
|
||||
|
||||
void prepChart(void)
|
||||
{
|
||||
chartXaxis_spr.createSprite(CHART_W, CHART_X_AXIS_OFFSET);
|
||||
chartYaxis_spr.createSprite(CHART_Y_AXIS_OFFSET, CHART_H);
|
||||
//draw X-axis
|
||||
chartXaxis_spr.drawLine(0, 0, CHART_W, 0, CHART_LINE_COLOR);
|
||||
//draw Y-axis
|
||||
chartYaxis_spr.drawLine(CHART_Y_AXIS_OFFSET - 1, 0, CHART_Y_AXIS_OFFSET - 1, CHART_H, CHART_LINE_COLOR);
|
||||
|
||||
//draw Y axis labels
|
||||
uint16_t tickIndex = (CHART_H - CHART_X_AXIS_OFFSET) / CHART_Y_TICKS;
|
||||
chartXaxis_spr.setTextColor(CHART_TEXT_COLOR);
|
||||
chartYaxis_spr.setTextColor(CHART_TEXT_COLOR);
|
||||
|
||||
for (int i = 0; i < CHART_Y_TICKS; i++)
|
||||
{
|
||||
//tick value
|
||||
uint16_t y_tick_step = calcTempY(tickIndex * (i + 1)); //CHART_TEMP_MAX - ((CHART_TEMP_MAX - CHART_TEMP_MIN) / CHART_Y_TICKS * i + 1) + CHART_TEMP_MIN;
|
||||
chartYaxis_spr.drawLine(CHART_Y_AXIS_OFFSET - 8, tickIndex * (i + 1), CHART_Y_AXIS_OFFSET, tickIndex * (i + 1), CHART_LINE_COLOR);
|
||||
chartYaxis_spr.setTextDatum(BR_DATUM);
|
||||
chartYaxis_spr.drawString(String(y_tick_step), CHART_Y_AXIS_OFFSET - 3, tickIndex * (i + 1), CHART_FONT);
|
||||
}
|
||||
|
||||
//draw X axis labels
|
||||
tickIndex = (CHART_W - CHART_Y_AXIS_OFFSET) / CHART_X_TICKS;
|
||||
for (int i = 0; i < CHART_X_TICKS + 1; i++)
|
||||
{
|
||||
uint16_t x_tick_step = (CHART_TIME_MAX / CHART_X_TICKS * (i));
|
||||
chartXaxis_spr.drawLine(tickIndex * i + CHART_Y_AXIS_OFFSET - 1, 0, tickIndex * i + CHART_Y_AXIS_OFFSET - 1, 8, CHART_LINE_COLOR);
|
||||
chartXaxis_spr.setTextDatum(TR_DATUM);
|
||||
chartXaxis_spr.drawString(String(x_tick_step), tickIndex * i + CHART_Y_AXIS_OFFSET - 1, 3, CHART_FONT);
|
||||
}
|
||||
chartXaxis_spr.pushSprite(CHART_X, CHART_Y + CHART_H - CHART_X_AXIS_OFFSET);
|
||||
chartYaxis_spr.pushSprite(CHART_X, CHART_Y);
|
||||
}
|
||||
|
||||
void prepStatus(void)
|
||||
{
|
||||
looptime_spr.createSprite(80, tft.fontHeight(1) + 1);
|
||||
}
|
||||
|
||||
void updateStatus(void)
|
||||
{
|
||||
looptime_spr.fillSprite(TFT_BLACK);
|
||||
looptime_spr.setTextDatum(TL_DATUM);
|
||||
looptime_spr.setTextColor(TFT_WHITE);
|
||||
looptime_spr.drawNumber(getLooptime(), 1, 1, 1);
|
||||
looptime_spr.drawFloat(getProcessTime(), 2, 20, 1, 1);
|
||||
|
||||
looptime_spr.pushSprite(1, 1);
|
||||
}
|
||||
|
||||
void prepButtons(void)
|
||||
{
|
||||
const uint32_t button_width = tft.width() / BUTTONS_N;
|
||||
|
||||
for (int i = 0; i < BUTTONS_N; i++)
|
||||
{
|
||||
key[i].initButtonUL(&tft,
|
||||
(button_width * i) + BUTTON_PADDING,
|
||||
tft.height() - BUTTON_H,
|
||||
button_width - (BUTTON_PADDING * 2),
|
||||
BUTTON_H,
|
||||
TFT_BLUE, // Outline
|
||||
TFT_SKYBLUE, // Fill
|
||||
TFT_BLACK, // Text
|
||||
buttonlabels[i], // 10 Byte Label
|
||||
KEY_TEXTSIZE);
|
||||
|
||||
key[i].setLabelDatum(0, 2, MC_DATUM);
|
||||
key[i].drawButton(false, buttonNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(TOUCH_CS)
|
||||
void touch_calibrate()
|
||||
{
|
||||
uint16_t calData[5];
|
||||
uint8_t calDataOK = 0;
|
||||
|
||||
// Calibrate
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setCursor(20, 0);
|
||||
tft.setTextFont(2);
|
||||
tft.setTextSize(1);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
|
||||
tft.println("Touch corners as indicated");
|
||||
|
||||
tft.setTextFont(1);
|
||||
tft.println();
|
||||
|
||||
tft.calibrateTouch(calData, TFT_MAGENTA, TFT_BLACK, 15);
|
||||
|
||||
// Use this calibration code in setup():");
|
||||
// uint16_t calData[5] = { 0,0,0,0,0 };
|
||||
// tft.setTouch(calData);
|
||||
|
||||
//String calDatastr = "";
|
||||
for (uint8_t i = 0; i < 5; i++)
|
||||
{
|
||||
tft.printf("%d,", calData[i]);
|
||||
}
|
||||
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
void updateGUIButtons(void)
|
||||
{
|
||||
uint32_t timeNow = millis();
|
||||
if (timeNow - lastButtonTime > BUTTON_INTERVAL)
|
||||
{
|
||||
uint16_t t_x = 0, t_y = 0; // To store the touch coordinates
|
||||
bool pressed = ts.touched(); //.getTouch(&t_x, &t_y);
|
||||
if (pressed)
|
||||
{
|
||||
TS_Point p = ts.getPoint();
|
||||
t_x = p.x;
|
||||
t_y = p.y;
|
||||
}
|
||||
|
||||
for (uint8_t b = 0; b < BUTTONS_N; b++)
|
||||
{
|
||||
if (pressed && key[b].contains(t_x, t_y))
|
||||
{
|
||||
//Serial.println("key pressed");
|
||||
key[b].press(true); // tell the button it is pressed
|
||||
setButton(b, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Serial.println("key released");
|
||||
key[b].press(false); // tell the button it is NOT pressed
|
||||
setButton(b, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if any key has changed state
|
||||
for (uint8_t b = 0; b < BUTTONS_N; b++)
|
||||
{
|
||||
// If button was just pressed, redraw inverted button
|
||||
if (key[b].justPressed())
|
||||
{
|
||||
key[b].drawButton(true, buttonNames[b]);
|
||||
}
|
||||
|
||||
// If button was just released, redraw normal color button
|
||||
if (key[b].justReleased())
|
||||
{
|
||||
key[b].drawButton(false, buttonNames[b]);
|
||||
}
|
||||
}
|
||||
lastButtonTime = timeNow;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Setup
|
||||
// -------------------------------------------------------------------------
|
||||
void initLCD(void) {
|
||||
void initTouchScreen(void)
|
||||
{
|
||||
//ts.begin();
|
||||
if (!ts.begin(TOUCH_SDA, TOUCH_SCL, tft.width(), tft.height(), true, 40))
|
||||
{
|
||||
Serial.println("Unable to start touchscreen.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Touchscreen started.");
|
||||
}
|
||||
}
|
||||
|
||||
void initLCD(void)
|
||||
{
|
||||
tft.init();
|
||||
|
||||
tft.setRotation(TFT_ROTATION);
|
||||
tft.setTextFont(2);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.invertDisplay(false);
|
||||
//tft.setTextColor(TFT_WHITE);
|
||||
tft.setRotation(0);
|
||||
#if defined(TOUCH_CS)
|
||||
//touch_calibrate();
|
||||
tft.setTouch(calData);
|
||||
#endif
|
||||
|
||||
initTouchScreen();
|
||||
|
||||
}
|
||||
|
||||
String showValue(String designator, float value, String unit)
|
||||
{
|
||||
String text;
|
||||
//text.clear();
|
||||
if (designator != "")
|
||||
{
|
||||
text = designator;
|
||||
text += " ";
|
||||
}
|
||||
text += value;
|
||||
text += " ";
|
||||
text += unit;
|
||||
return text;
|
||||
prepStatus();
|
||||
prepButtons();
|
||||
prepChart();
|
||||
prepReflowstate();
|
||||
prepTargetChart();
|
||||
prepOutput();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Main loop
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
|
||||
uint32_t lastLCDupdate = 0;
|
||||
|
||||
void handleLCD()
|
||||
{
|
||||
tft.drawString(showValue("Temp", getTemperature(), "grC"), 10, 10);
|
||||
updateStatus();
|
||||
uint32_t timeNow = millis();
|
||||
if (timeNow - lastLCDupdate > LCD_INTERVAL)
|
||||
{
|
||||
updateGUIButtons();
|
||||
updateReflowState();
|
||||
updateTargetChart();
|
||||
updateOutput();
|
||||
lastLCDupdate = timeNow;
|
||||
}
|
||||
}
|
||||
|
||||
void loopScreen(void)
|
||||
{
|
||||
}
|
||||
@@ -1,9 +1,79 @@
|
||||
#include "Arduino.h"
|
||||
#include "board.h"
|
||||
|
||||
#include "Setup202_SSD1351_128.h"
|
||||
#include <TFT_eSPI.h> // Include the graphics library
|
||||
#include "status.h"
|
||||
|
||||
#define TFT_WIDTH 240
|
||||
#define TFT_HEIGT 320
|
||||
#define TFT_DEFAULT_R 4
|
||||
#define TFT_ROTATION 0 //2 = upsidedown
|
||||
|
||||
#define LCD_INTERVAL 100
|
||||
|
||||
#define BUTTON_H 60
|
||||
#define BUTTON_W TFT_WIDTH
|
||||
#define BUTTONS_N 3
|
||||
#define BUTTON_PADDING 2
|
||||
#define BUTTON_RADIUS 8
|
||||
#define BUTTON_COLOR TFT_BLUE
|
||||
#define BUTTON_INTERVAL 20
|
||||
|
||||
#define KEY_TEXTSIZE 1 // Font size multiplier
|
||||
|
||||
#define CHART_X 0
|
||||
#define CHART_Y 40
|
||||
#define CHART_Y_AXIS_OFFSET 24
|
||||
#define CHART_X_AXIS_OFFSET 10
|
||||
#define CHART_W TFT_WIDTH - 5
|
||||
#define CHART_H 200
|
||||
#define CHART_FONT 1
|
||||
|
||||
#define CHART_TIME_MAX 500 //time scale in seconds
|
||||
#define CHART_TEMP_MIN 20 //offset in degrees
|
||||
#define CHART_TEMP_MAX 240 //degrees
|
||||
#define CHART_Y_TICKS 10
|
||||
#define CHART_X_TICKS 7
|
||||
#define CHART_LINE_COLOR TFT_WHITE
|
||||
#define CHART_TEXT_COLOR TFT_RED
|
||||
#define CHART_TARGET_COLOR TFT_LIGHTGREY
|
||||
#define CHART_ACTUAL_COLOR TFT_RED
|
||||
#define CHART_BG_COLOR TFT_BLACK
|
||||
|
||||
#define STATE_X 0
|
||||
#define STATE_Y 13
|
||||
#define STATE_W TFT_WIDTH
|
||||
#define STATE_H 24
|
||||
#define STATE_FONT 2
|
||||
#define STATE_OFFSET 3
|
||||
#define STATE_F_COLOR TFT_BLACK
|
||||
#define STATE_R TFT_DEFAULT_R
|
||||
#define STATE_BG_COLOR TFT_GREEN
|
||||
|
||||
#define TEMP_W 60
|
||||
#define TEMP_H 40
|
||||
#define TEMP_X CHART_W - TEMP_W - 20//allign right
|
||||
#define TEMP_Y 40
|
||||
#define TEMP_FONT 2
|
||||
#define TEMP_F_COLOR TFT_WHITE
|
||||
#define TEMP_BG_COLOR TFT_BLUE
|
||||
#define TEMP_R TFT_DEFAULT_R
|
||||
#define TEMP_LABEL_X 2
|
||||
#define TEMP_VALUE_X 20
|
||||
|
||||
#define OUTPUT_W 12
|
||||
#define OUTPUT_H 12
|
||||
#define OUTPUT_R 5
|
||||
#define OUTPUT_Y 0
|
||||
#define OUTPUT_X TFT_WIDTH - OUTPUT_W - 2
|
||||
#define OUTPUT_ON_COLOR TFT_RED
|
||||
#define OUTPUT_OFF_COLOR TFT_WHITE
|
||||
#define OUTPUT_BG TFT_BLACK
|
||||
|
||||
|
||||
|
||||
#define DEBOUNCE_MS 100
|
||||
|
||||
void initLCD(void);
|
||||
void handleLCD(void);
|
||||
|
||||
void loopScreen(void);
|
||||
|
||||
@@ -4,29 +4,25 @@
|
||||
#include "lcd.h"
|
||||
#include "thermo.h"
|
||||
#include "button.h"
|
||||
#include "heater.h"
|
||||
#include "status.h"
|
||||
#include "controlloop.h"
|
||||
|
||||
void setup()
|
||||
{
|
||||
// put your setup code here, to run once:
|
||||
initStatus();
|
||||
initLCD();
|
||||
initThermo();
|
||||
initButton();
|
||||
initHeater();
|
||||
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
initControlLoop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// put your main code here, to run repeatedly:
|
||||
handleLCD();
|
||||
handleThermo();
|
||||
handleButton();
|
||||
handleHeater();
|
||||
|
||||
digitalWrite(LED_BUILTIN, 1);
|
||||
delay(500);
|
||||
digitalWrite(LED_BUILTIN, 0);
|
||||
delay(500);
|
||||
handleStatus();
|
||||
handleControlLoop();
|
||||
}
|
||||
41
reflow_plate_fw/src/status.cpp
Normal file
41
reflow_plate_fw/src/status.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "status.h"
|
||||
|
||||
#include "controlloop.h"
|
||||
|
||||
uint64_t timelast = 0;
|
||||
uint64_t blinkrate = 500;
|
||||
bool ledstate = false;
|
||||
uint32_t looptime = 0;
|
||||
uint32_t looptimelast = 0;
|
||||
|
||||
void initStatus(void)
|
||||
{
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
Serial.begin(115200);
|
||||
delay(500);
|
||||
Serial.println("Heat Plate controller V1");
|
||||
}
|
||||
|
||||
void handleStatus(void)
|
||||
{
|
||||
uint64_t timenow = millis();
|
||||
if(timenow - timelast > blinkrate)
|
||||
{
|
||||
timelast = timenow;
|
||||
ledstate = !ledstate;
|
||||
digitalWrite(LED_BUILTIN, ledstate);
|
||||
}
|
||||
|
||||
looptime = timenow - looptimelast;
|
||||
looptimelast = timenow;
|
||||
}
|
||||
|
||||
uint32_t getLooptime(void)
|
||||
{
|
||||
return looptime;
|
||||
}
|
||||
|
||||
double getReflowTime(void)
|
||||
{
|
||||
return getProcessTime();
|
||||
}
|
||||
9
reflow_plate_fw/src/status.h
Normal file
9
reflow_plate_fw/src/status.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "board.h"
|
||||
|
||||
|
||||
void initStatus(void);
|
||||
void handleStatus(void);
|
||||
uint32_t getLooptime(void);
|
||||
@@ -1,46 +1,73 @@
|
||||
#include "thermo.h"
|
||||
#include "controlloop.h"
|
||||
|
||||
Thermocouple* thermocouple = NULL;
|
||||
//MAX6675 thermocouple(THERM_SS, THERM_MISO, THERM_CLK);
|
||||
MAX31855 thermocouple(THERM_CLK, THERM_SS, THERM_MISO); //uint8_t CS, uint8_t MISO);
|
||||
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void initThermo() {
|
||||
// initialize the Thermocouple
|
||||
//Adafruit_MAX31855 thermocouple(THERM_CLK, THERM_SS, THERM_MISO);
|
||||
|
||||
Thermocouple* originThermocouple = new MAX6675_Thermocouple(THERM_CL, THERM_CS, THERM_SO);
|
||||
thermocouple = new AverageThermocouple(
|
||||
originThermocouple,
|
||||
READINGS_NUMBER,
|
||||
DELAY_TIME
|
||||
);
|
||||
uint32_t thermo_lastTime = 0;
|
||||
|
||||
/* OR
|
||||
thermocouple = new AverageThermocouple(
|
||||
new MAX6675_Thermocouple(SCK_PIN, CS_PIN, SO_PIN),
|
||||
READINGS_NUMBER,
|
||||
DELAY_TIME
|
||||
);
|
||||
*/
|
||||
}
|
||||
float lastTemperature = 0;
|
||||
float internal = 0;
|
||||
|
||||
// the loop function runs over and over again forever
|
||||
void handleThermo(void) {
|
||||
// Reads temperature
|
||||
const double celsius = thermocouple->readCelsius();
|
||||
const double kelvin = thermocouple->readKelvin();
|
||||
const double fahrenheit = thermocouple->readFahrenheit();
|
||||
bool simulation = false;
|
||||
#define SIM_TEMP_STEP 1
|
||||
#define SIM_TEMP_COOL 0.08
|
||||
#define SIM_INTERVAL 100
|
||||
uint32_t simTimer = 0;
|
||||
uint32_t sampleTimer = 0;
|
||||
|
||||
// Output of information
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(celsius);
|
||||
Serial.print(" C, ");
|
||||
Serial.print(kelvin);
|
||||
Serial.print(" K, ");
|
||||
Serial.print(fahrenheit);
|
||||
Serial.println(" F");
|
||||
|
||||
delay(100); // optionally, only to delay the output of information in the example.
|
||||
}
|
||||
|
||||
double getTemperature(void)
|
||||
void initThermo()
|
||||
{
|
||||
return thermocouple->readCelsius();
|
||||
thermocouple.begin();
|
||||
if (simulation)
|
||||
{
|
||||
lastTemperature = TEMPERATURE_ROOM - 20;
|
||||
}
|
||||
}
|
||||
|
||||
void handleThermo(void)
|
||||
{
|
||||
uint32_t timeNow = millis();
|
||||
if (simulation)
|
||||
{
|
||||
|
||||
if (timeNow - simTimer > SIM_INTERVAL)
|
||||
{
|
||||
if (getOutputState())
|
||||
{
|
||||
lastTemperature += SIM_TEMP_STEP;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lastTemperature > TEMPERATURE_ROOM - 20)
|
||||
{
|
||||
lastTemperature -= SIM_TEMP_COOL;
|
||||
}
|
||||
}
|
||||
simTimer = timeNow;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (timeNow - sampleTimer > THERMO_INTERVAL)
|
||||
{
|
||||
int state = thermocouple.read();
|
||||
lastTemperature = thermocouple.getTemperature();
|
||||
internal = thermocouple.getInternal();
|
||||
sampleTimer = timeNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float getTemperature(void)
|
||||
{
|
||||
return lastTemperature; //lastTemperature;
|
||||
}
|
||||
|
||||
bool getThermoCoupleFault(void)
|
||||
{
|
||||
return thermocouple.genericError();
|
||||
}
|
||||
|
||||
@@ -2,26 +2,15 @@
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "board.h"
|
||||
#include <Thermocouple.h>
|
||||
#include <MAX6675_Thermocouple.h>
|
||||
#include <AverageThermocouple.h>
|
||||
|
||||
//#include "max6675.h"
|
||||
#include "MAX31855.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
How many readings are taken to determine a mean temperature.
|
||||
The more values, the longer a calibration is performed,
|
||||
but the readings will be more accurate.
|
||||
*/
|
||||
#define READINGS_NUMBER 10
|
||||
|
||||
/**
|
||||
Delay time between a temperature readings
|
||||
from the temperature sensor (ms).
|
||||
*/
|
||||
#define DELAY_TIME 10
|
||||
#define THERMO_INTERVAL 200
|
||||
#define SMOOTHING_FACTOR 2
|
||||
|
||||
void initThermo(void);
|
||||
void handleThermo(void);
|
||||
double getTemperature(void);
|
||||
float getTemperature(void);
|
||||
bool getThermoCoupleFault(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user