mirror of
https://github.com/ArduinoHannover/Maiskolben.git
synced 2025-09-01 17:12:35 +02:00
Version 2.0
This commit is contained in:
89
Maiskolben_GUI/Maiskolben_GUI.pde
Normal file
89
Maiskolben_GUI/Maiskolben_GUI.pde
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import processing.serial.*;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
static int gWidth = 400;
|
||||||
|
static int gHeight = 450;
|
||||||
|
static int frequency = 10; // receive data every 1/f seconds
|
||||||
|
|
||||||
|
Serial Maiskolben;
|
||||||
|
java.util.LinkedList<Integer> temperature = new java.util.LinkedList<Integer>();
|
||||||
|
float pidValue;
|
||||||
|
int setPoint;
|
||||||
|
int secs;
|
||||||
|
boolean off, standby, standby_layoff;
|
||||||
|
int[] stored = new int[3];
|
||||||
|
PGraphics history;
|
||||||
|
|
||||||
|
JToggleButton on = new JToggleButton();
|
||||||
|
JToggleButton stby = new JToggleButton();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
size(50,1);
|
||||||
|
surface.setResizable(true);
|
||||||
|
surface.setSize(gWidth+200,gHeight);
|
||||||
|
Object[] list = Serial.list();
|
||||||
|
JComboBox serialPort = new JComboBox(list);
|
||||||
|
Object[] params = {"Select serial Port:",serialPort};
|
||||||
|
Object[] opts = {"Select","Exit"};
|
||||||
|
int opt = JOptionPane.showOptionDialog(null, params, "Select Maiskolben", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, opts, opts[0]);
|
||||||
|
if (opt == JOptionPane.CANCEL_OPTION) System.exit(0);
|
||||||
|
else {
|
||||||
|
Maiskolben = new Serial(this, (String)serialPort.getSelectedItem(), 115200);
|
||||||
|
Maiskolben.bufferUntil(10);
|
||||||
|
}
|
||||||
|
history = createGraphics(gWidth,gHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw() {
|
||||||
|
if (Maiskolben != null && Maiskolben.available() > 0) {
|
||||||
|
//println("Received something!");
|
||||||
|
String line = Maiskolben.readStringUntil(10);
|
||||||
|
if (line != null) {
|
||||||
|
String values[] = line.split(";");
|
||||||
|
if (values.length < 9) println("zu wenig!");
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
secs = (secs+1)%frequency;
|
||||||
|
for (int i = 0; i < 3; stored[i] = Integer.parseInt(values[i++]));
|
||||||
|
off = values[3].equals("1");
|
||||||
|
standby = values[4].equals("1");
|
||||||
|
standby_layoff = values[5].equals("1");
|
||||||
|
setPoint = Integer.parseInt(values[6]);
|
||||||
|
temperature.add(Integer.parseInt(values[7]));
|
||||||
|
if (temperature.size() > gWidth) temperature.remove(0);
|
||||||
|
pidValue = Float.parseFloat(values[8]);
|
||||||
|
history.beginDraw();
|
||||||
|
history.background(50);
|
||||||
|
history.stroke(150);
|
||||||
|
for (int i = 50; i < gHeight; i+=50) {
|
||||||
|
history.line(0,i,gWidth,i);
|
||||||
|
}
|
||||||
|
for (int i = (temperature.size() == gWidth)?secs:0; i < gWidth; i+=frequency) {
|
||||||
|
history.line(gWidth-i,0,gWidth-i,gHeight);
|
||||||
|
}
|
||||||
|
history.stroke(255);
|
||||||
|
int lastV = temperature.getFirst();
|
||||||
|
int x = 0;
|
||||||
|
for (int temp : temperature) {
|
||||||
|
history.line(x,gHeight-lastV,++x,gHeight-(lastV = temp));
|
||||||
|
}
|
||||||
|
history.endDraw();
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
background(0);
|
||||||
|
image(history,0,0);
|
||||||
|
text(off?"Off":"On",gWidth+10,10);
|
||||||
|
text(standby?"Standby":"Active",gWidth+10,30);
|
||||||
|
text(standby_layoff?"In Holder":"",gWidth+10,50);
|
||||||
|
text("Set Temperature "+setPoint,gWidth+10,70);
|
||||||
|
if (temperature.size() != 0)
|
||||||
|
text("Current Temperature "+temperature.getLast(),gWidth+10,90);
|
||||||
|
}
|
@@ -1,15 +1,17 @@
|
|||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <Adafruit_GFX.h>
|
#include <Adafruit_GFX.h>
|
||||||
#include <Adafruit_PCD8544.h>
|
#include <Adafruit_PCD8544.h>
|
||||||
|
#include <PID_v1.h>
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
#include "TimerOne.h"
|
#include "TimerOne.h"
|
||||||
|
|
||||||
#define VERSION 100
|
#define VERSION 100
|
||||||
#define EEPROM_CHECK 42
|
#define EEPROM_CHECK 42
|
||||||
|
//#define HAS_BATTERY
|
||||||
|
|
||||||
#define STBY_TEMP 150
|
#define STBY_TEMP 150
|
||||||
//SOFTWARE CAN'T MEASURE MORE THAN 422, IF SET TO >= 422 IT'S LIKELY TO KILL YOUR TIP!
|
//SOFTWARE CAN'T MEASURE MORE THAN 422 DUE TO RESISTOR CONFIGURATION, IF SET TO >= 422 IT'S LIKELY TO KILL YOUR TIP!
|
||||||
//If read 1024 on Analog in, the tip is turned off.
|
//If read 1024 on Analog in, the tip is turned off
|
||||||
#define MAX_TEMP 400
|
#define MAX_TEMP 400
|
||||||
#define MIN_TEMP 100
|
#define MIN_TEMP 100
|
||||||
|
|
||||||
@@ -30,10 +32,15 @@
|
|||||||
#define SW_UP A5
|
#define SW_UP A5
|
||||||
#define BATTERY_IN A6
|
#define BATTERY_IN A6
|
||||||
|
|
||||||
|
#define kp 0.1
|
||||||
|
#define ki 0.0001
|
||||||
|
#define kd 0.0
|
||||||
|
|
||||||
#define TIME_DISP_REFRESH_IN_MS 300
|
#define TIME_DISP_REFRESH_IN_MS 300
|
||||||
#define TIME_SW_POLL_IN_MS 10
|
#define TIME_SW_POLL_IN_MS 10
|
||||||
#define DELAY_BEFORE_MEASURE 10
|
#define DELAY_BEFORE_MEASURE 10
|
||||||
#define DELAY_MAIN_LOOP 10
|
#define DELAY_MAIN_LOOP 10
|
||||||
|
#define PID_SAMPLE_TIME 10
|
||||||
|
|
||||||
#define ADC_TO_TEMP_GAIN 0.39
|
#define ADC_TO_TEMP_GAIN 0.39
|
||||||
#define ADC_TO_TEMP_OFFSET 23.9
|
#define ADC_TO_TEMP_OFFSET 23.9
|
||||||
@@ -41,17 +48,21 @@
|
|||||||
|
|
||||||
#define NUM_DIFFS 8 //Dividable by 8
|
#define NUM_DIFFS 8 //Dividable by 8
|
||||||
|
|
||||||
boolean off = true, stby = true, stby_layoff = true, sw_stby_old = false, sw_up_old = false, sw_down_old = false, clear_display = true, store_invalid = true, error = false, menu = false;
|
volatile boolean off = true, stby = true, stby_layoff = true, sw_stby_old = false, sw_up_old = false, sw_down_old = false, clear_display = true, store_invalid = true, error = false, menu = false;
|
||||||
uint16_t stored[3] = {250, 300, 350}, set_t = 150, cur_t, set_t_old, cur_t_old;
|
uint16_t stored[3] = {250, 300, 350}, set_t = 150, cur_t, set_t_old, cur_t_old;
|
||||||
|
double pid_val, cur_td, set_td;
|
||||||
uint8_t pwm, store_to = 255, contrast = 50;
|
uint8_t pwm, store_to = 255, contrast = 50;
|
||||||
uint16_t cnt_disp_refresh = TIME_DISP_REFRESH_IN_MS, cnt_sw_poll, cnt_but_press, cnt_off_press, cnt_but_store;
|
uint16_t cnt_disp_refresh = TIME_DISP_REFRESH_IN_MS, cnt_sw_poll, cnt_but_press, cnt_off_press, cnt_but_store;
|
||||||
float battery_voltage;
|
float battery_voltage;
|
||||||
uint16_t last_measured;
|
uint16_t last_measured;
|
||||||
int16_t last_diffs[NUM_DIFFS];
|
int16_t last_diffs[NUM_DIFFS];
|
||||||
uint8_t array_index, array_count;
|
uint8_t array_index, array_count;
|
||||||
|
uint32_t sendNext;
|
||||||
|
|
||||||
Adafruit_PCD8544 display = Adafruit_PCD8544(10, 9, -1);
|
Adafruit_PCD8544 display = Adafruit_PCD8544(10, 9, -1);
|
||||||
|
|
||||||
|
PID heaterPID(&cur_td, &pid_val, &set_td, kp, ki, kd, DIRECT);
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
digitalWrite(HEATER_PWM, LOW);
|
digitalWrite(HEATER_PWM, LOW);
|
||||||
pinMode(HEATER_PWM, OUTPUT);
|
pinMode(HEATER_PWM, OUTPUT);
|
||||||
@@ -70,9 +81,10 @@ void setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//PWM Prescaler = 1024
|
//PWM Prescaler = 1024
|
||||||
TCCR2B = TCCR2B & 0xFF;
|
TCCR2B = TCCR2B & 0b11111000 | 7;
|
||||||
|
delay(500);
|
||||||
display.begin();
|
display.begin();
|
||||||
|
delay(500);
|
||||||
display.clearDisplay();
|
display.clearDisplay();
|
||||||
if (EEPROM.read(0) != EEPROM_CHECK) {
|
if (EEPROM.read(0) != EEPROM_CHECK) {
|
||||||
EEPROM.update(0, EEPROM_CHECK);
|
EEPROM.update(0, EEPROM_CHECK);
|
||||||
@@ -86,14 +98,15 @@ void setup() {
|
|||||||
set_t = EEPROM.read(8) << 8;
|
set_t = EEPROM.read(8) << 8;
|
||||||
set_t |= EEPROM.read(9);
|
set_t |= EEPROM.read(9);
|
||||||
setContrast(EEPROM.read(10));
|
setContrast(EEPROM.read(10));
|
||||||
delay(500);
|
|
||||||
|
|
||||||
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
Serial.println("DIFF SUM;SET TEMPERATURE;IS TEMPERATURE;DUTY CYCLE;VOLTAGE");
|
//Serial.println("DIFF SUM;SET TEMPERATURE;IS TEMPERATURE;DUTY CYCLE;VOLTAGE");
|
||||||
last_measured = getTemperature();
|
last_measured = getTemperature();
|
||||||
Timer1.initialize(1000);
|
Timer1.initialize(1000);
|
||||||
Timer1.attachInterrupt(timer_isr);
|
Timer1.attachInterrupt(timer_isr);
|
||||||
|
heaterPID.SetMode(AUTOMATIC);
|
||||||
|
sendNext = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateEEPROM() {
|
void updateEEPROM() {
|
||||||
@@ -120,6 +133,7 @@ int getTemperature() {
|
|||||||
uint16_t adcValue = analogRead(TEMP_SENSE); // read the input
|
uint16_t adcValue = analogRead(TEMP_SENSE); // read the input
|
||||||
if (adcValue >= 1015) { //Illegal value
|
if (adcValue >= 1015) { //Illegal value
|
||||||
analogWrite(HEATER_PWM, 0);
|
analogWrite(HEATER_PWM, 0);
|
||||||
|
setOff(true);
|
||||||
return 999;
|
return 999;
|
||||||
} else {
|
} else {
|
||||||
analogWrite(HEATER_PWM, pwm); //switch heater back to last value
|
analogWrite(HEATER_PWM, pwm); //switch heater back to last value
|
||||||
@@ -292,11 +306,18 @@ void timer_disp_refresh() {
|
|||||||
disp = true;
|
disp = true;
|
||||||
}
|
}
|
||||||
if (off) {
|
if (off) {
|
||||||
if (clr) {
|
if (clr || ((cur_t_old != cur_t) && ((cur_t_old == 999) || (cur_t == 999)))) {
|
||||||
display.fillRect(16, 0, 64, 24, WHITE);
|
if (cur_t == 999) {
|
||||||
display.setCursor(16,0);
|
display.fillRect(0,0,84,24, WHITE);
|
||||||
display.setTextSize(3);
|
display.setCursor(6,4);
|
||||||
display.print("OFF");
|
display.setTextSize(2);
|
||||||
|
display.print("NO TIP");
|
||||||
|
} else {
|
||||||
|
display.fillRect(0, 0, 84, 24, WHITE);
|
||||||
|
display.setCursor(16,0);
|
||||||
|
display.setTextSize(3);
|
||||||
|
display.print("OFF");
|
||||||
|
}
|
||||||
disp = true;
|
disp = true;
|
||||||
}
|
}
|
||||||
} else if (set_t_old != set_t || clr) {
|
} else if (set_t_old != set_t || clr) {
|
||||||
@@ -324,6 +345,7 @@ void timer_disp_refresh() {
|
|||||||
disp = true;
|
disp = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef HAS_BATTERY
|
||||||
if (battery_voltage > 1) {
|
if (battery_voltage > 1) {
|
||||||
display.fillRect(display.width()-11,0,10,6,BLACK);
|
display.fillRect(display.width()-11,0,10,6,BLACK);
|
||||||
display.drawRect(display.width()-10,1,8,4,WHITE);
|
display.drawRect(display.width()-10,1,8,4,WHITE);
|
||||||
@@ -334,6 +356,7 @@ void timer_disp_refresh() {
|
|||||||
setOff(true);
|
setOff(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (disp)
|
if (disp)
|
||||||
display.display();
|
display.display();
|
||||||
}
|
}
|
||||||
@@ -353,6 +376,7 @@ void timer_isr() {
|
|||||||
|
|
||||||
void setError() {
|
void setError() {
|
||||||
error = true;
|
error = true;
|
||||||
|
clear_display = true;
|
||||||
setOff(true);
|
setOff(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,67 +392,56 @@ void loop() {
|
|||||||
} else {
|
} else {
|
||||||
target = set_t;
|
target = set_t;
|
||||||
}
|
}
|
||||||
int16_t diff = target-cur_t;
|
|
||||||
cnt_temp_rise++;
|
|
||||||
//check the temperature rise is high enough
|
|
||||||
int16_t delta = cur_t-last_measured;
|
int16_t delta = cur_t-last_measured;
|
||||||
if (delta <= -20) {
|
if (!off && delta <= -20 && cur_td != 999) {
|
||||||
setError();
|
setError();
|
||||||
}
|
}
|
||||||
if (diff >= 15) {
|
|
||||||
if (delta < -5 && array_count > 2) {
|
set_td = target;
|
||||||
setError();
|
cur_td = cur_t;
|
||||||
} else {
|
int16_t diff = target-cur_t;
|
||||||
last_diffs[array_index%NUM_DIFFS] = delta;
|
cnt_temp_rise++;
|
||||||
array_count = min(array_count+1, NUM_DIFFS);
|
|
||||||
if (array_count >= NUM_DIFFS) {
|
|
||||||
int16_t delta_t = 0;
|
|
||||||
for (uint8_t i = 0; i < array_count; i++) {
|
|
||||||
delta_t += last_diffs[(array_index+NUM_DIFFS-i)%NUM_DIFFS];
|
|
||||||
}
|
|
||||||
if (delta_t < NUM_DIFFS/8*2) {
|
|
||||||
setError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
array_index++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
array_count = 0;
|
|
||||||
}
|
|
||||||
last_measured = cur_t;
|
last_measured = cur_t;
|
||||||
/*
|
|
||||||
if (cnt_temp_rise >= TEMP_RISE_TIME/DELAY_MAIN_LOOP) {
|
heaterPID.Compute();
|
||||||
//if risen less then 20deg then it's a sensor failure (tip not plugged in?)
|
if (error || off)
|
||||||
if (diff_old-diff < TEMP_MIN_RISE) {
|
|
||||||
error = true;
|
|
||||||
stby = true;
|
|
||||||
clear_display = true;
|
|
||||||
} else {
|
|
||||||
diff_old = diff;
|
|
||||||
cnt_temp_rise = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if (error)
|
|
||||||
pwm = 0;
|
pwm = 0;
|
||||||
else
|
else
|
||||||
pwm = max(0, min(255, diff*CTRL_GAIN));
|
pwm = min(255,pid_val*255);
|
||||||
|
//pwm = max(0, min(255, diff*CTRL_GAIN));
|
||||||
//reset counter if not heating that much
|
//reset counter if not heating that much
|
||||||
if (pwm < min(TEMP_MIN_RISE*CTRL_GAIN, 200)) cnt_temp_rise = 0;
|
if (pwm < min(TEMP_MIN_RISE*CTRL_GAIN, 200)) cnt_temp_rise = 0;
|
||||||
|
|
||||||
analogWrite(HEATER_PWM, pwm);
|
analogWrite(HEATER_PWM, pwm);
|
||||||
digitalWrite(HEAT_LED, cur_t <= target && (cur_t < target-5 || (millis()/1000)%2));
|
digitalWrite(HEAT_LED, cur_t+5 < target || (abs((int16_t)cur_t-(int16_t)target) <= 5 && (millis()/(stby?1000:500))%2));
|
||||||
battery_voltage = (analogRead(BATTERY_IN)*3*5/1024.0);
|
battery_voltage = (analogRead(BATTERY_IN)*3*5/1024.0);
|
||||||
Serial.print(delta);
|
if (sendNext <= millis()) {
|
||||||
Serial.print(";");
|
sendNext += 100;
|
||||||
Serial.print(set_t);
|
Serial.print(stored[0]);
|
||||||
Serial.print(";");
|
Serial.print(";");
|
||||||
Serial.print(cur_t);
|
Serial.print(stored[1]);
|
||||||
Serial.print(";");
|
Serial.print(";");
|
||||||
Serial.print(pwm);
|
Serial.print(stored[2]);
|
||||||
Serial.print(";");
|
Serial.print(";");
|
||||||
Serial.print(battery_voltage);
|
Serial.print(off?1:0);
|
||||||
Serial.println("V");
|
Serial.print(";");
|
||||||
Serial.flush();
|
Serial.print(stby?1:0);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(stby_layoff?1:0);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(set_t);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(cur_t);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(pid_val);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(battery_voltage);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(battery_voltage);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.println(battery_voltage);
|
||||||
|
Serial.flush();
|
||||||
|
}
|
||||||
delay(DELAY_MAIN_LOOP);
|
delay(DELAY_MAIN_LOOP);
|
||||||
}
|
}
|
505
Maiskolben_TFT/Maiskolben_TFT.ino
Normal file
505
Maiskolben_TFT/Maiskolben_TFT.ino
Normal file
@@ -0,0 +1,505 @@
|
|||||||
|
#include <SPI.h>
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Adafruit_ST7735.h>
|
||||||
|
#include <PID_v1.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include "TimerOne.h"
|
||||||
|
#include "definitions.h"
|
||||||
|
|
||||||
|
volatile boolean off = true, stby = true, stby_layoff = true, sw_stby_old = false, sw_up_old = false, sw_down_old = false, clear_display = true, store_invalid = true, menu = false;
|
||||||
|
volatile uint8_t pwm, threshold_counter;
|
||||||
|
volatile int16_t cur_t, last_measured;
|
||||||
|
volatile error_type error = NO_ERROR;
|
||||||
|
error_type error_old;
|
||||||
|
int16_t stored[3] = {250, 300, 350}, set_t = 150, set_t_old, cur_t_old, target_t;
|
||||||
|
double pid_val, cur_td, set_td;
|
||||||
|
uint8_t store_to = 255;
|
||||||
|
p_source power_source, power_source_old = NO_INIT;
|
||||||
|
boolean blink;
|
||||||
|
uint16_t cnt_measure_voltage, cnt_compute, cnt_sw_poll, cnt_but_press, cnt_off_press, cnt_but_store;
|
||||||
|
float v_c1, v_c2, v_c3;
|
||||||
|
uint8_t array_index, array_count;
|
||||||
|
uint32_t sendNext;
|
||||||
|
uint32_t last_temperature_drop;
|
||||||
|
boolean wasOff = true;
|
||||||
|
|
||||||
|
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, 0);
|
||||||
|
#define ST7735_GRAY 0x94B2
|
||||||
|
|
||||||
|
PID heaterPID(&cur_td, &pid_val, &set_td, kp, ki, kd, DIRECT);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
digitalWrite(HEATER_PWM, LOW);
|
||||||
|
pinMode(HEATER_PWM, OUTPUT);
|
||||||
|
pinMode(HEAT_LED, OUTPUT);
|
||||||
|
pinMode(TEMP_SENSE, INPUT);
|
||||||
|
pinMode(SW_T1, INPUT_PULLUP);
|
||||||
|
pinMode(SW_T2, INPUT_PULLUP);
|
||||||
|
pinMode(SW_T3, INPUT_PULLUP);
|
||||||
|
pinMode(SW_UP, INPUT_PULLUP);
|
||||||
|
pinMode(SW_DOWN, INPUT_PULLUP);
|
||||||
|
pinMode(STBY_NO, INPUT_PULLUP);
|
||||||
|
pinMode(SW_STBY, INPUT_PULLUP);
|
||||||
|
delay(100);
|
||||||
|
tft.initR(INITR_BLACKTAB);
|
||||||
|
tft.fillScreen(ST7735_BLACK);
|
||||||
|
tft.setRotation(1);
|
||||||
|
tft.drawBitmap(0, 20, maiskolben, 160, 64, ST7735_YELLOW);
|
||||||
|
tft.setCursor(20,86);
|
||||||
|
tft.setTextColor(ST7735_YELLOW);
|
||||||
|
tft.setTextSize(2);
|
||||||
|
tft.print("Maiskolben");
|
||||||
|
tft.setCursor(50,110);
|
||||||
|
tft.setTextSize(1);
|
||||||
|
tft.print("Version ");
|
||||||
|
tft.print(VERSION);
|
||||||
|
|
||||||
|
//PWM Prescaler = 1024
|
||||||
|
TCCR2B = TCCR2B & (0b11111000 | 7);
|
||||||
|
if (EEPROM.read(0) != EEPROM_CHECK) {
|
||||||
|
EEPROM.update(0, EEPROM_CHECK);
|
||||||
|
updateEEPROM();
|
||||||
|
}
|
||||||
|
stby = EEPROM.read(1);
|
||||||
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
|
stored[i] = EEPROM.read(2+i*2) << 8;
|
||||||
|
stored[i] |= EEPROM.read(3+i*2);
|
||||||
|
}
|
||||||
|
set_t = EEPROM.read(8) << 8;
|
||||||
|
set_t |= EEPROM.read(9);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 50; i++)
|
||||||
|
measureVoltage(); //measure average 50 times to get realistic results
|
||||||
|
|
||||||
|
Serial.begin(115200);
|
||||||
|
//Serial.println("DIFF SUM;SET TEMPERATURE;IS TEMPERATURE;DUTY CYCLE;VOLTAGE");
|
||||||
|
delay(3000);
|
||||||
|
tft.fillScreen(ST7735_BLACK);
|
||||||
|
last_measured = getTemperature();
|
||||||
|
Timer1.initialize(1000);
|
||||||
|
Timer1.attachInterrupt(timer_isr);
|
||||||
|
heaterPID.SetMode(AUTOMATIC);
|
||||||
|
sendNext = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateEEPROM() {
|
||||||
|
EEPROM.update(1, stby);
|
||||||
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
|
EEPROM.update(2+i*2, stored[i] >> 8);
|
||||||
|
EEPROM.update(3+i*2, stored[i] & 0xFF);
|
||||||
|
}
|
||||||
|
EEPROM.update(8, set_t >> 8);
|
||||||
|
EEPROM.update(9, set_t & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getTemperature() {
|
||||||
|
analogRead(TEMP_SENSE);//Switch ADC MUX
|
||||||
|
uint16_t adc = median(TEMP_SENSE);
|
||||||
|
if (adc >= 1020) { //Illegal value, tip not plugged in
|
||||||
|
analogWrite(HEATER_PWM, 0);
|
||||||
|
if (!off)
|
||||||
|
setError(NO_TIP);
|
||||||
|
return 999;
|
||||||
|
} else {
|
||||||
|
analogWrite(HEATER_PWM, pwm); //switch heater back to last value
|
||||||
|
}
|
||||||
|
return round(((float) adc)*ADC_TO_TEMP_GAIN+ADC_TO_TEMP_OFFSET); //apply linear conversion to actual temperature
|
||||||
|
}
|
||||||
|
|
||||||
|
void measureVoltage() {
|
||||||
|
analogRead(BAT_C1); //Switch analog MUX before measuring
|
||||||
|
v_c1 = v_c1*.9+(analogRead(BAT_C1)*5/1024.0)*.1;
|
||||||
|
analogRead(BAT_C2);
|
||||||
|
v_c2 = v_c2*.9+(analogRead(BAT_C2)*5/512.0)*.1;
|
||||||
|
analogRead(BAT_C3);
|
||||||
|
v_c3 = v_c3*.9+(analogRead(BAT_C3)*(5.0*1510.0)/(510.0*1024.0))*.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t median(uint8_t analogIn) {
|
||||||
|
uint16_t adcValue[3];
|
||||||
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
|
adcValue[i] = analogRead(analogIn); // read the input 3 times
|
||||||
|
}
|
||||||
|
uint16_t tmp;
|
||||||
|
if (adcValue[0] > adcValue[1]) {
|
||||||
|
tmp = adcValue[0];
|
||||||
|
adcValue[0] = adcValue[1];
|
||||||
|
adcValue[1] = tmp;
|
||||||
|
}
|
||||||
|
if (adcValue[1] > adcValue[2]) {
|
||||||
|
tmp = adcValue[1];
|
||||||
|
adcValue[1] = adcValue[2];
|
||||||
|
adcValue[2] = tmp;
|
||||||
|
}
|
||||||
|
if (adcValue[0] > adcValue[1]) {
|
||||||
|
tmp = adcValue[0];
|
||||||
|
adcValue[0] = adcValue[1];
|
||||||
|
adcValue[1] = tmp;
|
||||||
|
}
|
||||||
|
return adcValue[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_sw_poll() {
|
||||||
|
stby_layoff = !digitalRead(STBY_NO);
|
||||||
|
if (!digitalRead(SW_STBY)) {
|
||||||
|
if (cnt_off_press == 100) {
|
||||||
|
setOff(!off);
|
||||||
|
}
|
||||||
|
cnt_off_press = min(101, cnt_off_press+1);
|
||||||
|
} else {
|
||||||
|
if (cnt_off_press > 0 && cnt_off_press != 101) {
|
||||||
|
setStandby(!stby);
|
||||||
|
}
|
||||||
|
cnt_off_press = 0;
|
||||||
|
}
|
||||||
|
boolean t1 = !digitalRead(SW_T1);
|
||||||
|
boolean t2 = !digitalRead(SW_T2);
|
||||||
|
boolean t3 = !digitalRead(SW_T3);
|
||||||
|
|
||||||
|
//simultanious push of multiple buttons
|
||||||
|
if (t1 + t2 + t3 > 1) {
|
||||||
|
store_to = 255;
|
||||||
|
store_invalid = true;
|
||||||
|
} else if (error != NO_ERROR) {
|
||||||
|
if (!(t1 | t2 | t3)) {
|
||||||
|
store_invalid = false;
|
||||||
|
} else if (!store_invalid && t3) {
|
||||||
|
error = NO_ERROR; //dismiss
|
||||||
|
set_t_old = 0; //refresh set_t display
|
||||||
|
store_invalid = true; //wait for release
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//all buttons released
|
||||||
|
if (!(t1 | t2 | t3)) {
|
||||||
|
if (store_to != 255) {
|
||||||
|
if (cnt_but_store <= 100) {
|
||||||
|
set_t = stored[store_to];
|
||||||
|
setStandby(false);
|
||||||
|
updateEEPROM();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
store_to = 255;
|
||||||
|
store_invalid = false;
|
||||||
|
cnt_but_store = 0;
|
||||||
|
} else
|
||||||
|
//one button pressed
|
||||||
|
if (!store_invalid) {
|
||||||
|
store_to = t2 + 2*t3;
|
||||||
|
if (cnt_but_store > 100) {
|
||||||
|
if (set_t != stored[store_to] && !stby) {
|
||||||
|
stored[store_to] = set_t;
|
||||||
|
cnt_but_store = 100;
|
||||||
|
updateEEPROM();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cnt_but_store++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean sw_up = !digitalRead(SW_UP);
|
||||||
|
boolean sw_down = !digitalRead(SW_DOWN);
|
||||||
|
boolean sw_changed = (sw_up != sw_up_old) || (sw_down !=sw_down_old);
|
||||||
|
sw_up_old = sw_up;
|
||||||
|
sw_down_old = sw_down;
|
||||||
|
if((sw_up && sw_down) || !(sw_up || sw_down)) {
|
||||||
|
cnt_but_press = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(sw_up || sw_down) {
|
||||||
|
cnt_but_press++;
|
||||||
|
if((cnt_but_press >= 100) || sw_changed) {
|
||||||
|
setStandby(false);
|
||||||
|
if(sw_up && set_t < MAX_TEMP) set_t++;
|
||||||
|
else if (sw_down && set_t > MIN_TEMP) set_t--;
|
||||||
|
if(!sw_changed) cnt_but_press = 97;
|
||||||
|
updateEEPROM();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setStandby(boolean state) {
|
||||||
|
if (state == stby) return;
|
||||||
|
stby = state;
|
||||||
|
last_measured = cur_t;
|
||||||
|
last_temperature_drop = millis();
|
||||||
|
EEPROM.update(1, stby);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setOff(boolean state) {
|
||||||
|
if (state == off) return;
|
||||||
|
if (!state)
|
||||||
|
analogWrite(HEATER_PWM, 0);
|
||||||
|
if (power_source == POWER_USB && !state) {
|
||||||
|
state = true; //don't switch on, if powered via USB
|
||||||
|
setError(USB_ONLY);
|
||||||
|
}
|
||||||
|
off = state;
|
||||||
|
wasOff = true;
|
||||||
|
last_measured = cur_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void display() {
|
||||||
|
int16_t temperature = cur_t; //buffer volatile value
|
||||||
|
boolean yell = stby || (stby_layoff && blink);
|
||||||
|
tft.drawCircle(20,63,8, off?ST7735_RED:yell?ST7735_YELLOW:ST7735_GREEN);
|
||||||
|
tft.drawCircle(20,63,7,off?ST7735_RED:yell?ST7735_YELLOW:ST7735_GREEN);
|
||||||
|
tft.fillRect(19,55,3,3,ST7735_BLACK);
|
||||||
|
tft.drawFastVLine(20,53,10, off?ST7735_RED:yell?ST7735_YELLOW:ST7735_GREEN);
|
||||||
|
if (error != NO_ERROR) {
|
||||||
|
if (error != error_old) {
|
||||||
|
error_old = error;
|
||||||
|
tft.setTextSize(1);
|
||||||
|
tft.setTextColor(ST7735_RED, ST7735_BLACK);
|
||||||
|
tft.setCursor(0,96);
|
||||||
|
switch (error) {
|
||||||
|
case EXCESSIVE_FALL:
|
||||||
|
tft.print("Error: Temperature dropped\nTip slipped out?");
|
||||||
|
break;
|
||||||
|
case NOT_HEATING:
|
||||||
|
tft.print("Error: Not heating\nWeak power source or short");
|
||||||
|
break;
|
||||||
|
case BATTERY_LOW:
|
||||||
|
tft.print("Error: Battery low\nReplace or charge");
|
||||||
|
break;
|
||||||
|
case USB_ONLY:
|
||||||
|
tft.print("Error: Power too low\nConnect power >5V");
|
||||||
|
break;
|
||||||
|
case NO_TIP:
|
||||||
|
tft.print("Error: No tip connected\nTip slipped out?");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tft.setTextSize(2);
|
||||||
|
tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
|
||||||
|
tft.setCursor(10,112);
|
||||||
|
tft.print(" OK ");
|
||||||
|
|
||||||
|
tft.setTextColor(ST7735_RED, ST7735_BLACK);
|
||||||
|
tft.setCursor(54,26);
|
||||||
|
tft.setTextSize(3);
|
||||||
|
tft.print("ERR");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (error != error_old) {
|
||||||
|
tft.fillRect(0, 96, 160, 16, ST7735_BLACK);
|
||||||
|
error_old = NO_ERROR;
|
||||||
|
}
|
||||||
|
tft.setTextSize(2);
|
||||||
|
tft.setCursor(15,112);
|
||||||
|
tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
|
||||||
|
tft.print(stored[0]);
|
||||||
|
tft.write(' ');
|
||||||
|
tft.print(stored[1]);
|
||||||
|
tft.write(' ');
|
||||||
|
tft.print(stored[2]);
|
||||||
|
if (set_t_old != set_t) {
|
||||||
|
set_t_old = set_t;
|
||||||
|
tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
|
||||||
|
tft.setCursor(54,26);
|
||||||
|
tft.setTextSize(3);
|
||||||
|
tft.print(set_t);
|
||||||
|
tft.fillTriangle(149, 50, 159, 50, 154, 38, (set_t < MAX_TEMP) ? ST7735_WHITE : ST7735_GRAY);
|
||||||
|
tft.fillTriangle(149, 77, 159, 77, 154, 90, (set_t > MIN_TEMP) ? ST7735_WHITE : ST7735_GRAY);
|
||||||
|
}
|
||||||
|
if (!off && !stby) {
|
||||||
|
uint16_t tout = min(max(0,(last_temperature_drop + STANDBY_TIMEOUT - (millis()+500)/1000)), STANDBY_TIMEOUT);
|
||||||
|
tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
|
||||||
|
tft.setTextSize(2);
|
||||||
|
tft.setCursor(58,78);
|
||||||
|
tft.print(tout/60);
|
||||||
|
tft.write(':');
|
||||||
|
if (tout%60 < 10) tft.write('0');
|
||||||
|
tft.print(tout%60);
|
||||||
|
} else if (temperature != 999) {
|
||||||
|
tft.fillRect(54, 78, 60, 20, ST7735_BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cur_t_old != temperature) {
|
||||||
|
tft.setCursor(54,52);
|
||||||
|
tft.setTextSize(3);
|
||||||
|
if (temperature == 999) {
|
||||||
|
tft.setTextColor(ST7735_RED, ST7735_BLACK);
|
||||||
|
tft.print("ERR");
|
||||||
|
tft.setCursor(44,76);
|
||||||
|
tft.setTextSize(2);
|
||||||
|
tft.print("NO TIP");
|
||||||
|
} else {
|
||||||
|
if (cur_t_old == 999) {
|
||||||
|
tft.fillRect(44,76,72,16,ST7735_BLACK);
|
||||||
|
}
|
||||||
|
tft.setTextColor(off ? temperature < 50 ? ST7735_GREEN : ST7735_RED : tft.Color565(min(10,abs(temperature-target_t))*25, 250 - min(10,max(0,(abs(temperature-target_t)-10)))*25, 0), ST7735_BLACK);
|
||||||
|
if (temperature < 100) tft.write(' ');
|
||||||
|
tft.print(temperature);
|
||||||
|
}
|
||||||
|
if (temperature < cur_t_old)
|
||||||
|
tft.drawFastHLine((int)(temperature/2.6), 0, 160-(int)(temperature/2.6), ST7735_BLACK);
|
||||||
|
else if (cur_t != 999) {
|
||||||
|
for (int16_t i = 0; i < temperature/2.6; i++) {
|
||||||
|
tft.drawPixel(i, 0, tft.Color565(min(255, max(0, i*5)), min(255, max(0, 400-i*2.5)), 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cur_t_old = temperature;
|
||||||
|
}
|
||||||
|
if (v_c3 > 1.0) {
|
||||||
|
if (v_c3 < 5.0) {
|
||||||
|
power_source = POWER_USB;
|
||||||
|
} else if (v_c2 < 1.0) {
|
||||||
|
power_source = POWER_CORD;
|
||||||
|
} else {
|
||||||
|
power_source = POWER_LIPO;
|
||||||
|
}
|
||||||
|
if (power_source != power_source_old) {
|
||||||
|
tft.fillRect(0, 5, 128, 20, ST7735_BLACK);
|
||||||
|
tft.fillRect(11, 25, 21, 20, ST7735_BLACK);
|
||||||
|
switch (power_source) {
|
||||||
|
case POWER_LIPO:
|
||||||
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
|
tft.fillRect(11, 5+i*14, 20, 12, ST7735_WHITE);
|
||||||
|
tft.fillRect(12, 6+i*14, 18, 10, ST7735_BLACK);
|
||||||
|
tft.drawFastVLine(31,8+i*14,6,ST7735_WHITE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case POWER_USB:
|
||||||
|
tft.setTextSize(1);
|
||||||
|
tft.setTextColor(ST7735_RED, ST7735_BLACK);
|
||||||
|
tft.setCursor(0,5);
|
||||||
|
tft.print("USB power only\nConnect power supply.");
|
||||||
|
if (!off) setError(USB_ONLY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
power_source_old = power_source;
|
||||||
|
}
|
||||||
|
if (power_source == POWER_CORD) {
|
||||||
|
tft.setTextSize(2);
|
||||||
|
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
|
||||||
|
tft.setCursor(0,5);
|
||||||
|
tft.print(v_c3);
|
||||||
|
tft.print("V ");
|
||||||
|
} else if (power_source == POWER_LIPO) {
|
||||||
|
float volt[] = {v_c1, v_c2-v_c1, v_c3-v_c2};
|
||||||
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
|
if (volt[i] < 3.20) {
|
||||||
|
setError(BATTERY_LOW);
|
||||||
|
tft.fillRect(13, 7+14*i, max(1,min(16,(volt[i]-3.0)*14.2)), 8, blink?ST7735_RED:ST7735_BLACK);
|
||||||
|
} else {
|
||||||
|
tft.fillRect(13, 7+14*i, max(1,min(16,(volt[i]-3.0)*14.2)), 8, tft.Color565(250-min(250, max(0, (volt[i]-3.4)*1000.0)), max(0,min(250, (volt[i]-3.15)*1000.0)), 0));
|
||||||
|
}
|
||||||
|
tft.fillRect(13+max(1,min(16,(volt[i]-3.0)*14.2)), 7+14*i, 17-max(1,min(16,(volt[i]-3.0)*14.2)), 8, ST7735_BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (target_t-cur_t > 0.715*exp(0.0077*target_t)) {
|
||||||
|
//if (cur_t / (double)target_t < STANDBY_TEMPERATURE_DROP) {
|
||||||
|
if (stby && !wasOff) {
|
||||||
|
setStandby(false);
|
||||||
|
} else {
|
||||||
|
last_temperature_drop = millis()/1000;
|
||||||
|
}
|
||||||
|
} else if (wasOff) {
|
||||||
|
wasOff = false;
|
||||||
|
}
|
||||||
|
if (!off && !stby && millis()/1000 > (last_temperature_drop + STANDBY_TIMEOUT)) {
|
||||||
|
setStandby(true);
|
||||||
|
}
|
||||||
|
blink = !blink;
|
||||||
|
}
|
||||||
|
|
||||||
|
void compute() {
|
||||||
|
cur_t = getTemperature();
|
||||||
|
if (off) {
|
||||||
|
target_t = 0;
|
||||||
|
if (cur_t < TEMP_THRESHOLD) {
|
||||||
|
threshold_counter = TEMP_UNDER_THRESHOLD; //reset counter
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (stby_layoff || stby) {
|
||||||
|
target_t = STBY_TEMP;
|
||||||
|
} else {
|
||||||
|
target_t = set_t;
|
||||||
|
}
|
||||||
|
if (cur_t-last_measured <= -30 && last_measured != 999) {
|
||||||
|
setError(EXCESSIVE_FALL); //decrease of more than 30 degree is not realistic, short of ring and gnd is common.
|
||||||
|
}
|
||||||
|
if (cur_t < TEMP_THRESHOLD) {
|
||||||
|
if (threshold_counter == 0) {
|
||||||
|
setError(NOT_HEATING); //temperature is not reached in desired time, short of sensor and gnd too?
|
||||||
|
} else {
|
||||||
|
threshold_counter--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
threshold_counter = THRES_MAX_DECEED; //reset counter to a smaller value to allow small oscillation of temperature
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set_td = target_t;
|
||||||
|
cur_td = cur_t;
|
||||||
|
last_measured = cur_t;
|
||||||
|
|
||||||
|
heaterPID.Compute();
|
||||||
|
if (error != NO_ERROR || off)
|
||||||
|
pwm = 0;
|
||||||
|
else
|
||||||
|
pwm = min(255,pid_val*255);
|
||||||
|
analogWrite(HEATER_PWM, pwm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer_isr() {
|
||||||
|
if (cnt_compute >= TIME_COMPUTE_IN_MS+DELAY_BEFORE_MEASURE) {
|
||||||
|
compute();
|
||||||
|
cnt_compute=0;
|
||||||
|
} else if(cnt_compute >= TIME_COMPUTE_IN_MS) {
|
||||||
|
analogWrite(HEATER_PWM, 0); //switch off heater to let the low pass settle
|
||||||
|
}
|
||||||
|
cnt_compute++;
|
||||||
|
|
||||||
|
if(cnt_sw_poll >= TIME_SW_POLL_IN_MS){
|
||||||
|
timer_sw_poll();
|
||||||
|
cnt_sw_poll=0;
|
||||||
|
}
|
||||||
|
cnt_sw_poll++;
|
||||||
|
|
||||||
|
if(cnt_measure_voltage >= TIME_MEASURE_VOLTAGE_IN_MS) {
|
||||||
|
measureVoltage();
|
||||||
|
cnt_measure_voltage=0;
|
||||||
|
}
|
||||||
|
cnt_measure_voltage++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setError(error_type e) {
|
||||||
|
error = e;
|
||||||
|
setOff(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
analogWrite(HEAT_LED, pwm);
|
||||||
|
//Switch to following if the oscillation of the led bothers you
|
||||||
|
//digitalWrite(HEAT_LED, cur_t+5 < target || (abs((int16_t)cur_t-(int16_t)target) <= 5 && (millis()/(stby?1000:500))%2));
|
||||||
|
|
||||||
|
if (sendNext <= millis()) {
|
||||||
|
sendNext += 100;
|
||||||
|
Serial.print(stored[0]);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(stored[1]);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(stored[2]);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(off?1:0);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(stby?1:0);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(stby_layoff?1:0);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(set_t);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(cur_t);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(pid_val);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(v_c2>1.0?v_c1:0.0);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.print(v_c2);
|
||||||
|
Serial.print(";");
|
||||||
|
Serial.println(v_c3);
|
||||||
|
Serial.flush();
|
||||||
|
display();
|
||||||
|
}
|
||||||
|
delay(DELAY_MAIN_LOOP);
|
||||||
|
}
|
149
Maiskolben_TFT/definitions.h
Normal file
149
Maiskolben_TFT/definitions.h
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
#define VERSION 103
|
||||||
|
#define EEPROM_CHECK 42
|
||||||
|
//#define HAS_BATTERY
|
||||||
|
|
||||||
|
#define STBY_TEMP 150
|
||||||
|
//SOFTWARE CAN'T MEASURE MORE THAN 422 DUE TO RESISTOR CONFIGURATION, IF SET TO >= 422 IT'S LIKELY TO KILL YOUR TIP!
|
||||||
|
//If read 1024 on Analog in, the tip is turned off
|
||||||
|
#define MAX_TEMP 400
|
||||||
|
#define MIN_TEMP 100
|
||||||
|
|
||||||
|
#define STANDBY_TIMEOUT 240 // seconds without any significant temperature drop, if exceeded it will standby
|
||||||
|
|
||||||
|
#define TEMP_THRESHOLD 50 //threshold voltage, that must be exceeded in given time:
|
||||||
|
#define TEMP_UNDER_THRESHOLD 150 //*10ms
|
||||||
|
#define THRES_MAX_DECEED 2 //max times the threshold temperature may be undercut by the current temperature
|
||||||
|
|
||||||
|
//Temperature in degree to rise at least in given time
|
||||||
|
#define TEMP_MIN_RISE 10
|
||||||
|
//Time in that the temperature must rise by the set temperature
|
||||||
|
#define TEMP_RISE_TIME 1000
|
||||||
|
|
||||||
|
#define SW_STBY 2
|
||||||
|
#define HEATER_PWM 3
|
||||||
|
#define SW_DOWN 4
|
||||||
|
#define HEAT_LED 5
|
||||||
|
#define SW_UP 6
|
||||||
|
#define SW_T3 7
|
||||||
|
#define SW_T2 8
|
||||||
|
#define SW_T1 9
|
||||||
|
#define TFT_CS 10
|
||||||
|
#define TEMP_SENSE A0
|
||||||
|
#define STBY_NO A1
|
||||||
|
#define BAT_C3 A2
|
||||||
|
#define BAT_C2 A3
|
||||||
|
#define BAT_C1 A4
|
||||||
|
#define TFT_DC A5
|
||||||
|
|
||||||
|
#define kp 0.03
|
||||||
|
#define ki 0.00001
|
||||||
|
#define kd 0.0
|
||||||
|
|
||||||
|
#define TIME_COMPUTE_IN_MS 10
|
||||||
|
#define TIME_MEASURE_VOLTAGE_IN_MS 200
|
||||||
|
#define TIME_SW_POLL_IN_MS 10
|
||||||
|
#define DELAY_BEFORE_MEASURE 10
|
||||||
|
#define DELAY_MAIN_LOOP 10
|
||||||
|
#define PID_SAMPLE_TIME 10
|
||||||
|
|
||||||
|
#define ADC_TO_TEMP_GAIN 0.39
|
||||||
|
#define ADC_TO_TEMP_OFFSET 23.9
|
||||||
|
#define CTRL_GAIN 10
|
||||||
|
|
||||||
|
typedef enum POWER_SOURCE {
|
||||||
|
NO_INIT,
|
||||||
|
POWER_USB,
|
||||||
|
POWER_CORD,
|
||||||
|
POWER_LIPO
|
||||||
|
} p_source;
|
||||||
|
typedef enum ERROR_TYPE {
|
||||||
|
NO_ERROR,
|
||||||
|
EXCESSIVE_FALL,
|
||||||
|
NOT_HEATING,
|
||||||
|
NO_TIP,
|
||||||
|
BATTERY_LOW,
|
||||||
|
USB_ONLY
|
||||||
|
} error_type;
|
||||||
|
|
||||||
|
const unsigned char maiskolben [] PROGMEM = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xe0, 0x60, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xcf, 0xff, 0xa0,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xdc, 0xf7,
|
||||||
|
0x18, 0x47, 0x89, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
|
||||||
|
0x26, 0x78, 0xc6, 0x33, 0x9c, 0x7f, 0x0c, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x01, 0x08, 0x23, 0x49, 0xe6, 0x1b, 0xff, 0xf8, 0x39, 0xd0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xc5, 0x31, 0xcf, 0xe7, 0x3f, 0xfe, 0x14, 0x21, 0x08,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x47, 0xf9, 0xff, 0xff, 0xcc,
|
||||||
|
0x40, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x4e,
|
||||||
|
0x0f, 0xc1, 0x08, 0x04, 0x63, 0x00, 0x21, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x47, 0xe0, 0x0c, 0x01, 0x08, 0x07, 0xaf, 0x80, 0x60, 0x84, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x02, 0x0c, 0x01, 0x8c, 0xc7, 0xa4, 0x80, 0xe0, 0xf4,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x0c, 0x60, 0x9f, 0xc7,
|
||||||
|
0xf0, 0xf3, 0x33, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x83,
|
||||||
|
0x0e, 0xe0, 0x77, 0x69, 0x9a, 0xf7, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x0c, 0xfd, 0xb7, 0xb6, 0x67, 0x79, 0x9f, 0xfe, 0xee, 0x12, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xfc, 0xf3, 0xbe, 0xff, 0xfb, 0xff, 0xf8, 0x46, 0x12,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcd, 0xcf, 0xbc, 0x63, 0x18, 0x6e,
|
||||||
|
0x21, 0x80, 0x42, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8c, 0xfe,
|
||||||
|
0x08, 0x42, 0x08, 0x44, 0x21, 0x48, 0x42, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x06, 0x84, 0xe2, 0x1e, 0x4a, 0x18, 0x44, 0xe1, 0xc0, 0x63, 0x0f, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x63, 0x3c, 0x7b, 0x18, 0x6e, 0x60, 0x80, 0x31, 0x07,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x65, 0xec, 0x71, 0x08, 0x22,
|
||||||
|
0x10, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x39,
|
||||||
|
0x84, 0x21, 0x8c, 0x33, 0x10, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x08, 0x38, 0x84, 0x00, 0x08, 0x32, 0x10, 0x02, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x58, 0x10, 0x84, 0x00, 0x08, 0x20, 0x10, 0x03, 0xf1, 0x9f,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x70, 0x44, 0x60, 0x08, 0x23,
|
||||||
|
0x30, 0xc4, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00,
|
||||||
|
0xc7, 0x1f, 0xff, 0xff, 0x1f, 0x84, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x08, 0xc0, 0x7f, 0x82, 0x10, 0x8c, 0x03, 0x08, 0x84, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x78, 0x82, 0x10, 0x88, 0x01, 0x08, 0x84, 0x10, 0x87,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7c, 0x28, 0x82, 0x18, 0xc8, 0x21,
|
||||||
|
0x08, 0x82, 0x10, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x28,
|
||||||
|
0x42, 0x08, 0xc0, 0x21, 0x8c, 0x42, 0x10, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf0, 0x00,
|
||||||
|
0x00, 0x3f, 0xfc, 0x18, 0x42, 0x08, 0xc4, 0x11, 0x8c, 0x42, 0x10, 0x83, 0x80, 0x00, 0x00, 0x00,
|
||||||
|
0x7f, 0xff, 0xfe, 0x89, 0xfc, 0xff, 0x94, 0x0c, 0x42, 0x08, 0x44, 0x30, 0x88, 0x42, 0x10, 0x03,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0x06, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x0c, 0x62, 0x00, 0x04, 0x00,
|
||||||
|
0x88, 0x42, 0x10, 0x03, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x04, 0x1c,
|
||||||
|
0x20, 0x00, 0x88, 0x00, 0x88, 0x42, 0x10, 0xc7, 0x06, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x07, 0x80, 0x1c, 0x23, 0x10, 0xc8, 0x00, 0x8c, 0x43, 0x30, 0xf9, 0x01, 0xf0, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x37, 0x9d, 0xbc, 0x30, 0xfe, 0xe7, 0x6f, 0x11,
|
||||||
|
0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0x04, 0x4c, 0xe7, 0x9e, 0x2f,
|
||||||
|
0x31, 0x8e, 0x64, 0x31, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xce, 0x23,
|
||||||
|
0x8f, 0xe7, 0x1d, 0xc7, 0x31, 0x8c, 0x64, 0x11, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x02, 0x46, 0x30, 0xcf, 0xf6, 0x1c, 0xe6, 0x39, 0xcc, 0x64, 0x11, 0x00, 0x06, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x44, 0x38, 0xcc, 0x76, 0x18, 0xc2, 0x3d, 0x2c, 0x6c, 0x13,
|
||||||
|
0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x44, 0x38, 0xcc, 0x66, 0x10, 0x86,
|
||||||
|
0x31, 0x08, 0x48, 0x13, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x44, 0x38,
|
||||||
|
0xc0, 0x44, 0x10, 0x84, 0x21, 0x00, 0x48, 0x12, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x01, 0x40, 0x30, 0x80, 0x44, 0x01, 0x04, 0x20, 0x00, 0x48, 0x1e, 0x00, 0x01, 0x80, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x84, 0x44, 0x21, 0x04, 0x20, 0x0c, 0xfc, 0x26,
|
||||||
|
0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x86, 0xcc, 0x21, 0x04,
|
||||||
|
0x23, 0x0f, 0x8e, 0xc2, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00,
|
||||||
|
0x8e, 0xff, 0xff, 0x0f, 0xfb, 0xf9, 0x84, 0x46, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x71, 0xf0, 0x6c, 0x31, 0xc4, 0x40, 0x19, 0x00, 0x46, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xb8, 0x30, 0x4c, 0x21, 0x04, 0x40, 0x11, 0x00, 0x46,
|
||||||
|
0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x20, 0x20, 0x48, 0x20, 0x00,
|
||||||
|
0x02, 0x11, 0x08, 0x44, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x28,
|
||||||
|
0x20, 0x08, 0x02, 0x00, 0x80, 0x11, 0x08, 0x4c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x22, 0x18, 0x20, 0x00, 0x02, 0x00, 0x80, 0x13, 0x1c, 0xd8, 0x00, 0x00, 0x03, 0x40,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x18, 0x20, 0x00, 0x42, 0x08, 0x84, 0x1d, 0xe6, 0x38,
|
||||||
|
0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x18, 0x21, 0x1c, 0x7e, 0x0e,
|
||||||
|
0x7f, 0x90, 0x44, 0x38, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x7c,
|
||||||
|
0x7c, 0xcc, 0x31, 0x88, 0x42, 0x10, 0x44, 0x38, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x1e, 0x42, 0x10, 0x08, 0x21, 0x08, 0x42, 0x10, 0x84, 0x78, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x40, 0x00, 0x08, 0x20, 0x08, 0x62, 0x10, 0x8c, 0x70,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x08,
|
||||||
|
0xc6, 0x21, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8,
|
||||||
|
0x60, 0x08, 0x44, 0x3f, 0xff, 0xe7, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
122
README.md
122
README.md
@@ -1,2 +1,122 @@
|
|||||||
# Maiskolben
|
# Maiskolben
|
||||||
SMD Solderingstation
|
|
||||||
|
## SMD Lötstation, kompatibel zu Weller-Lötspitzen
|
||||||
|
|
||||||
|
Weller baut seit Jahren *die* Lötstationen für den professionellen Bereich.
|
||||||
|
Die WMRP/WXRP-Stationen heben sich durch ihre aktiven Lötspitzen von anderen Produkten ab.
|
||||||
|
Mit einer außergewöhnlich kurzen Aufheizzeit im Sekundenbereich, einer direkt in der Spitze integrierten Temperaturmessung und dementsprechend schnelle Nachregulierung in Sekundenbruchteilen sind die Spitzen in der Industrie äußerst beliebt.
|
||||||
|
Die Spitzen selbst sind für 40€ im Handel erhältlich, die original Weller-Station kostet an die 600€.
|
||||||
|
Für den einfachen Maker oder Hobbyist auf keinen Fall ein Produkt, das beim Onlineshopping ohne weitere Überlegungen in den Warenkorb wandert.
|
||||||
|
Der *Maiskolben* hingegen ist eine erschwingliche Lösung für lediglich 40€, mit der die Spitzen ebenso angesteuert werden können.
|
||||||
|
|
||||||
|
* Betrieb mit 12V Netzteil oder 3s LiPo (Modellbau-Akku)
|
||||||
|
* Spannungsüberwachung (bei Akku für alle 3 Zellen und automatische Abschaltung bei zu geringer Ladung)
|
||||||
|
* Einfaches Wechseln von Spitzen mittels Klinken-Buchse/-Kabel
|
||||||
|
* 3 individuelle Temperatur-Presets
|
||||||
|
* Temperaturbereich von 100-400°C
|
||||||
|
* Gut ablesbares Farbdisplay mit allen nötigen Informationen
|
||||||
|
* Auto-Standby (entweder sensor- oder zeitgesteuert auf 150°C)
|
||||||
|
* Auto-Wakeup (entweder sensorgesteuert oder durch berühren von Lötschwamm, Messingwolle oder Lötstelle)
|
||||||
|
* USB-Schnittstelle zur Überwachung oder Steuerung mittels PC
|
||||||
|
* Potentialausgleich-/ESD-Buchse (über 1MΩ an GND)
|
||||||
|
* Optisches Feedback der Heizleistung durch LED
|
||||||
|
* Open-Source-Software auf Basis von Arduino
|
||||||
|
* Software-Update kann per USB eingespielt werden
|
||||||
|
|
||||||
|
## Stromzufuhr
|
||||||
|
|
||||||
|
Die Stromzufuhr wird wahlweise über die Hohlstecker-Buchse (10-18V) *ODER* die JST-XH4 (11,1V) Buchse angeschlossen.
|
||||||
|
Niemals beide gleichzeitig anschließen!
|
||||||
|
Der Lötkolben (Weller RT-XX, z.B. RT-1 für feine Lötarbeiten) wird über die Klinkenbuchse mit einer Verlängerung angesteckt.
|
||||||
|
|
||||||
|
## Display
|
||||||
|
|
||||||
|
Das Display zeigt mittig in weißer Schrift die Soll-Temperatur, darunter, sofern eine Spitze eingesteckt ist, die aktuelle Ist-Temperatur.
|
||||||
|
Bei eingeschaltetem Lötkolben erscheint zusätzlich noch die Zeit, nach der sich der Lötkolben automatisch in den Standby versetzt.
|
||||||
|
Der Balken am oberen Bildschirmrand spiegelt die Ist-Temperatur wieder.
|
||||||
|
Oben Links wird die Spannung bzw. die Ladezustände der einzelnen Zellen angezeigt.
|
||||||
|
Links wird durch das Power-Symbol der aktuelle Zustand (aus = rot, Standby = gelb, an = grün) signalisiert.
|
||||||
|
Am unteren Rand sind die drei Presets zu sehen.
|
||||||
|
|
||||||
|
## Bedienung
|
||||||
|
|
||||||
|
Nach dem Anstecken von Netzteil und Lötspitze kann die Station durch halten der Power-Taste (unten rechts) eingeschaltet werden.
|
||||||
|
Basierend auf der letzten Einstellung wird die angezeigte Soll- (Power-Symbol grün) oder die Standby-Temperatur (Symbol gelb) angefahren.
|
||||||
|
Mittels der Tasten rechts vom Display (Pfeile) lässt sich die Soll-Temperatur nach oben und unten korrigieren.
|
||||||
|
Sollte einer der Pfeile auf dem Display ausgegraut sein, so lässt sich über diese Temperatur hinaus keine weitere Änderung mehr vornehmen (100 ≥ T ≥ 400).
|
||||||
|
Mittels der Preset-Tasten unter dem Bildschirm lassen sich voreingestellte Temperaturen als Soll-Temperatur setzen und die Station gleichzeitig aus dem Standby aufwecken.
|
||||||
|
Durch gedrückthalten einer der drei Tasten wird der dort gespeicherte Wert durch die aktuelle Soll-Temperatur überschrieben.
|
||||||
|
Wird die Power-Taste nur kurz gedrückt, so wird der Standby-Zustand umgeschaltet.
|
||||||
|
|
||||||
|
## Fehlermeldungen
|
||||||
|
|
||||||
|
#### USB power only/Connect power supply; Power too low/Connect power >5V
|
||||||
|
Die Lötstation wird entweder nur über USB oder eine Spannungsquelle mit knapp 5V versorgt.
|
||||||
|
Zum Betrieb wird ein adäquates Netzteil oder Akku benötigt (≥40W)
|
||||||
|
|
||||||
|
#### NO TIP; No tip connected/Tip slipped out?
|
||||||
|
Es wurde keine Spitze eingesteckt oder nicht erkannt.
|
||||||
|
Es kann sein, dass die Spitze defekt ist oder nicht richtig in der Buchse steckt.
|
||||||
|
|
||||||
|
#### Temperature dropped/Tip slipped out?
|
||||||
|
Es wurde ein zu großer Temperaturabfall bemerkt und die Wahrscheinlichkeit besteht, dass die Spitze leicht aus der Buchse herausgerutscht ist.
|
||||||
|
Durch das Herausrutschen kann eine Verbindung zwischen Masse und dem Sensor hergestellt werden, sodass die erkannte Temperatur beim Offset von 24°C liegt.
|
||||||
|
|
||||||
|
#### Not heating/Weak power source or short
|
||||||
|
Entweder kann die Stromversorgung nicht genug Leistung bringen, um die Spitze in einem angemessenen Zeitraum aufzuheizen oder es liegt wie bei obigem Fehler ein Kurzschluss von Masse und Sensor vor.
|
||||||
|
|
||||||
|
#### Battery low/Replace or charge
|
||||||
|
Der Akku hat auf mindestens einer Zelle eine zu geringe Spannung und sollte ersetzt oder geladen werden.
|
||||||
|
|
||||||
|
Fehlermeldungen müssen durch OK bestätigt werden.
|
||||||
|
Die Fehlermeldungen können nicht unterdrückt werden, sollte allerdings mehrfach hintereinander eine Meldung bestätigt und die Station wieder eingeschaltet werden, kann dies zu übermäßigem Erwärmen der Lötspitze führen.
|
||||||
|
|
||||||
|
## Software-Update
|
||||||
|
|
||||||
|
Um die aktuellste Software auf den Maiskolbe zu übertragen, muss zunächst die [Arduino-IDE](https://www.arduino.cc/en/Main/Software) heruntergeladen werden.
|
||||||
|
In diesem Repository befinden sich zwei Programme, zum einen Maiskolben_LCD für die Hardware-Revision 1.0 und Maiskolben_TFT für Hardware-Revisionen ab 1.5.
|
||||||
|
Die .ino Datei kann mit Arduino geöffnet werden.
|
||||||
|
Der Serielle-Port muss nach Herstellen einer Verbindung zwischen Maiskolben und PC unter _Werkzeuge_ > _Port_ ausgewählt werden.
|
||||||
|
Unter umständen muss zuvor noch der [Treiber](http://www.wch.cn/download/CH341SER_ZIP.html) für den USB-Seriell-Wandler installiert werden.
|
||||||
|
Als _Board_ sollte _Arduino Nano_ mit _Prozessor_: _ATmega328_ ausgewählt werden.
|
||||||
|
Über _Sketch_ > _Hochladen_ bzw. den Pfeil nach Rechts in der oberen Leiste kann das Programm übertragen werden.
|
||||||
|
|
||||||
|
Unter umständen müssen vorher folgende Libraries noch über _Sketch_ > _Bibliothek einbinden_ > _.ZIP Bibliothek hinzufügen..._ eingebunden werden:
|
||||||
|
|
||||||
|
* [TimerOne](https://github.com/PaulStoffregen/TimerOne)
|
||||||
|
* [PID_v1](https://github.com/br3ttb/Arduino-PID-Library/)
|
||||||
|
* [Adafruit_ST7735](https://github.com/adafruit/Adafruit-ST7735-Library)
|
||||||
|
* [Adafruit_GFX](https://github.com/adafruit/Adafruit-GFX-Library)
|
||||||
|
|
||||||
|
### Changelog
|
||||||
|
|
||||||
|
* 2.0 Initiale Version für GitHub (TFT)
|
||||||
|
* Auto-Standby hinzugefügt
|
||||||
|
* Parameter angepasst
|
||||||
|
|
||||||
|
### Achtung!
|
||||||
|
|
||||||
|
Zur eigenen Sicherheit vor einem Software-Update die Lötspitze entfernen.
|
||||||
|
Zwar wird die Heizspannung beim Übertragen deaktiviert, dennoch kann es vereinzelt zu Fehlfunktionen und dadurch bedingtem unbeschränkten Aufheizen der Spitze kommen.
|
||||||
|
|
||||||
|
Modifikationen an der Software sind auf eigene Gefahr des Nutzers.
|
||||||
|
|
||||||
|
## Umbauten
|
||||||
|
|
||||||
|
Nachfolgend werden Modifikationen beschrieben, die die Funktionen des Maiskolben erweitern.
|
||||||
|
Für eigens durchgeführte Änderungen kann keine Haftung übernommen werden.
|
||||||
|
|
||||||
|
### Ablage-Sensor nachrüsten
|
||||||
|
|
||||||
|
Statt des automatischen Standbys nach einer bestimmten Zeit kann auch der Standby durch einen Ablage-Sensor erzwungen werden.
|
||||||
|
Auf der Platine befinden sich Kontakte mit STBY, 5V und GND.
|
||||||
|
Um den Standby zu aktivieren muss STBY mit GND verbunden werden, um wieder aufzuwachen muss die Verbindung getrennt werden.
|
||||||
|
Das Schalten von STBY nach GND kann entweder durch einen Schalter erfolgen, der beim auflegen der Spitze auslöst, alternativ mit einem Hall- oder Reed-Sensor.
|
||||||
|
Für letzteres muss an dem Ende des Klinken-Kabels, an dem die Spitze eingesteckt wird, ein Magnet angebracht werden, der den Sensor dann auslöst.
|
||||||
|
|
||||||
|
### Stromversorgungs-Schalter
|
||||||
|
|
||||||
|
Ab Hardware-Revision 1.5 gibt es auf der Platinenunterseite eine Lötbrücke mit der Beschriftung ON/OFF.
|
||||||
|
Bis einschließlich Revision 1.9 wird beim Durchtrennen dieser Brücke die gesamte Stromversorgung unterbrochen.
|
||||||
|
Ab Revision 1.11 wird hingegen nur noch die Zuleitung des LiPos getrennt.
|
||||||
|
An den beiden Lötpunkten können nach dem Durchtrennen der Leiterbahn Kabel zu einem Schalter gelötet werden, mit dem sich die Stromversorgung unterbrechen lässt.
|
Reference in New Issue
Block a user