Compare commits

...

15 Commits
v1.01 ... v1.04

Author SHA1 Message Date
Ben V. Brown
0f3bb4c356 Bump version 1.04 2017-05-18 21:20:57 +10:00
Ben V. Brown
0ebaab5847 Add more intuitive idle screen with prompts 2017-05-18 21:20:26 +10:00
Ben V. Brown
203a7c154b Add official Schematic 2017-05-18 19:51:55 +10:00
Ben V. Brown
ebfe457f65 Add Temperature calibration, improve temp accuracy 2017-05-18 19:51:47 +10:00
Ben V. Brown
8c73aa0de4 Use set/clear logic on buttons 2017-05-17 23:36:53 +10:00
Ben V. Brown
53a1b9b7f4 Add sensitivity selection menu 2017-05-17 22:53:21 +10:00
Ben V. Brown
c9d0d5bdb3 Update Readme, making windows warning bold 2017-05-17 13:37:22 +10:00
Ben V. Brown
4f9e738501 Update Readme to add link to releases page 2017-05-17 12:33:17 +10:00
Ben V. Brown
fcaf909a54 Improve button response times (100ms filter) 2017-05-15 23:19:56 +10:00
Ben V. Brown
9b51750a1d Backend work for supporting adjusting movement sensitivity 2017-05-15 23:00:42 +10:00
Ben V. Brown
fceb81287e Patch to fix left handed screen 2017-01-23 20:52:46 +11:00
Ben V. Brown
c3d8d246dc Update readme 2017-01-23 19:45:23 +11:00
Ben V. Brown
1f7cdf9694 For temperature mode force reading 2017-01-23 19:39:56 +11:00
Ben V. Brown
b2db129ab8 V1.02 Add Thermometer Mode 2017-01-23 19:33:03 +11:00
Ben V. Brown
b7e4249d2e Use both buttons to exit soldering instead of B 2017-01-22 21:19:26 +11:00
19 changed files with 351 additions and 134 deletions

View File

@@ -1,27 +1,28 @@
# TS100
This is a complete open source re-write of the software for the ts100 soldering iron.
This project is feature complete for use as a soldering iron, but is still open to ideas and suggestions.
This was started to remove the need for USB for changing system settings.
The software has similar functionality to the original firmware.
This project was started to remove the need for USB for changing system settings.
In the latest official firmware they have also added a settings menu system, so it is still worth comparing the two firmwares to select your preferred option.
## Features Working
* Soldering / Temperature control
* Full PID Iron Temp
* Full PID iron temperature control
* Adjusting temperature
* Automatic sleep
* Motion wake support
* Basic settings menu
* Settings menu
* Input voltage UVLO measurement
* Saving settings to flash for persistence
* Improved GUI
* Improved GUI Fonts
* Use hardware I2C for communications
* Can disable movement detection if desired
## Features still to be implemented
* Manual Temp Calibration
# Upgrading your ts100 iron
This is completely safe, if it goes wrong just put the .hex file from the official website onto the unit and your back to the old firmware :)
This is completely safe, if it goes wrong just put the .hex file from the official website onto the unit and your back to the old firmware. Downloads for the hex files to flash are available on the [releases page.](https://github.com/Ralim/ts100/releases)
**You will need a windows computer (7,8,10 tested), using the normal windows explorer to load the firmware.
The bootloader does not appear to work under mac or linux at the moment.**
1. Hold the button closest to the tip, and plug in the USB to the computer.
2. The unit will appear as a USB drive.
@@ -29,10 +30,19 @@ This is completely safe, if it goes wrong just put the .hex file from the offici
4. The unit will disconnect and reconnect.
5. The filename will have changed to end in .RDY or .ERR .
6. If it ends with .RDY your done! Otherwise something went wrong.
7. If it went wrong try on a windows computer, some Mac / Linux machines do not play well with their boot loader.
7. Disconnect the USB and power up the iron. You're good to go.
For the more adventurerous out there, you can also load this firmware onto the device using a SWD programmer.
On the bottom of the MCU riser pcb, there are 4 pads for programming.
There is a complete device flash backup included in this repository. (Note this includes the bootloader, so will need a SWD programmer to load onto the unit). Please do not use the backup of the bootloader for anything malicious, its only saved here for those who are tinkering with their iron and decide to replace it.
# New Menu System
This new firmware uses a new menu system to allow access to the settings on the device.
This menu can be accessed as shown in following flow chart, in the settings numbers roll over from top to bottom.
![TS100: Software Menu](http://ralimtek.com/images/TS100.png "Fairly easy to learn")
![TS100: Software Menu](TS100.png "Fairly easy to learn")
# Version Changes:
V1.02
- Adds hold both buttons on IDLE to access the therometer mode.
- Changes the exit soldering mode to be holding both buttons (Like original firmware).

Binary file not shown.

BIN
TS100.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

View File

@@ -103,7 +103,7 @@
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="fr.ac6.managedbuild.config.gnu.cross.exe.release.1113492345" name="Release" parent="fr.ac6.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary and Printing size information:" postbuildStep="arm-none-eabi-objcopy -O binary &quot;${BuildArtifactFileBaseName}.elf&quot; &quot;${BuildArtifactFileBaseName}.bin&quot;; arm-none-eabi-size -B &quot;${BuildArtifactFileName}&quot;">
<configuration artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="fr.ac6.managedbuild.config.gnu.cross.exe.release.1113492345" name="Release" parent="fr.ac6.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary and Printing size information:" postbuildStep="arm-none-eabi-objcopy -O binary &quot;${BuildArtifactFileBaseName}.elf&quot; &quot;${BuildArtifactFileBaseName}.bin&quot;; arm-none-eabi-size -B &quot;${BuildArtifactFileName}&quot;;arm-none-eabi-objcopy -O ihex &quot;${BuildArtifactFileBaseName}.elf&quot; &quot;${BuildArtifactFileBaseName}.hex&quot;">
<folderInfo id="fr.ac6.managedbuild.config.gnu.cross.exe.release.1113492345." name="/" resourcePath="">
<toolChain id="fr.ac6.managedbuild.toolchain.gnu.cross.exe.release.668479481" name="Ac6 STM32 MCU GCC" superClass="fr.ac6.managedbuild.toolchain.gnu.cross.exe.release">
<option id="fr.ac6.managedbuild.option.gnu.cross.mcu.302274410" name="Mcu" superClass="fr.ac6.managedbuild.option.gnu.cross.mcu" value="STM32F103T8Ux" valueType="string"/>

View File

@@ -1 +1,2 @@
/Debug/
/Release/

View File

@@ -15,6 +15,6 @@
extern volatile uint16_t ADC1ConvertedValue[2];
uint16_t Get_ADC1Value(uint8_t i);
uint16_t readIronTemp(uint16_t calibration,uint8_t read);//read the iron temp in C X10
uint16_t readIronTemp(uint16_t calibration_temp, uint8_t read,uint16_t setPointTemp); //read the iron temp in C X10
uint16_t readDCVoltage();/*Get the system voltage X10*/
#endif /* ANALOG_H_ */

View File

@@ -97,4 +97,70 @@ const uint8_t FONT[]={
0x00,0x00,0x00,0x00,0x0F,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00,/*.*/
};
const uint8_t Iron_Base[] ={
0x00,0x20,0x60,0x60,0x60,0x60,0x60,0x60,0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x60,0x60,
0x60,0x60,0x60,0x60,0x60,0x70,0xF8,0x88,0x84,0x82,0x82,0x83,
0x83,0x83,0x83,0x83,0x83,0x82,0x82,0x82,0x82,0x83,0x83,0x83,
0x83,0x83,0x83,0x82,0x82,0x82,0x82,0x82,0x86,0x84,0x84,0x84,
0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
0x84,0x84,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE,0x00,
};
//The top pixel row for left arrow / on hint
const uint8_t Iron_LeftArrow_UP[] = {
0x00,0x7C,0x82,0x82,0x82,0x7C,0x00,0xFE,0x08,0x10,0x20,0xFE,//ON
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,0x88,
0x98,0xBF,0xBF,0x98,0x88,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,
};
const uint8_t Iron_LeftArrow_DOWN[] = {
0x00,0x7C,0x82,0x82,0x82,0x7C,0x00,0xFE,0x08,0x10,0x20,0xFE,//ON
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,0x10,
0x30,0x7E,0x7E,0x30,0x10,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,
};
//The top pixel row for both arrows /
const uint8_t Iron_BothArrows[] = {
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,0x88,
0x98,0xBF,0xBF,0x98,0x88,0x00,0x00,0x00,0x00,0x88,0x98,0xBF,
0xBF,0x98,0x88,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,
};
//The top pixel row for right arrow / settings hint
const uint8_t Iron_RightArrow_UP[] = {
0x00,0x8C,0x92,0x92,0x92,0x62,0x00,0xFE,0x92,0x92,0x92,0x82,//SE
0x00,0x02,0x02,0xFE,0x02,0x02,0x00,0x02,0x02,0xFE,0x02,0x02,//TT
0x00,0x00,0x82,0xFE,0x82,0x00,0x00,0xFE,0x08,0x10,0x20,0xFE,//IN
0x00,0x7C,0x82,0x82,0xA2,0x62,0x00,0x8C,0x92,0x92,0x92,0x62,//GS
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x98,0xBF,
0xBF,0x98,0x88,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,
};
const uint8_t Iron_RightArrow_DOWN[] = {
0x00,0x8C,0x92,0x92,0x92,0x62,0x00,0xFE,0x92,0x92,0x92,0x82,//SE
0x00,0x02,0x02,0xFE,0x02,0x02,0x00,0x02,0x02,0xFE,0x02,0x02,//TT
0x00,0x00,0x82,0xFE,0x82,0x00,0x00,0xFE,0x08,0x10,0x20,0xFE,//IN
0x00,0x7C,0x82,0x82,0xA2,0x62,0x00,0x8C,0x92,0x92,0x92,0x62,//GS
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x30,0x7E,
0x7E,0x30,0x10,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,
};
#endif /* FONT_H_ */

View File

@@ -15,7 +15,7 @@
#define __MMA8652FC__H
void StartUp_Accelerometer(void);//This is the only function we expose
void StartUp_Accelerometer(uint8_t sensitivity);//This is the only function we expose
//--------------MMA8652 Device ID----------------------------------------------//

View File

@@ -24,11 +24,19 @@ enum {
SLEEP,
COOLING,
UVLOWARN,
THERMOMETER,
DCINDISP,
TEMPCAL,
} operatingMode;
enum {
UVCO = 0, SLEEP_TEMP, SLEEP_TIME, MOTIONDETECT, TEMPDISPLAY,LEFTY
UVCO = 0,
SLEEP_TEMP,
SLEEP_TIME,
MOTIONDETECT,
MOTIONSENSITIVITY,
TEMPDISPLAY,
LEFTY,
} settingsPage;
void ProcessUI();

View File

@@ -18,7 +18,7 @@ u8* Oled_DrawArea(u8 x0, u8 y0, u8 wide, u8 high, u8* ptr);
void Set_ShowPos(u8 x, u8 y);
void Oled_DisplayFlip();
void GPIO_Init_OLED(void);
void Init_Oled(void);
void Init_Oled(uint8_t leftHanded);
u8* Data_Command(u8 len, u8* ptr);
void Clear_Screen(void);//Clear the screen
/*Functions for writing to the screen*/
@@ -26,6 +26,6 @@ void OLED_DrawString(char* string, uint8_t length);
void OLED_DrawChar(char c, uint8_t x);
void OLED_DrawTwoNumber(uint8_t in, uint8_t x);
void OLED_DrawThreeNumber(uint16_t in, uint8_t x);
void OLED_DrawIDLELogo();
#endif
/******************************** END OF FILE *********************************/

View File

@@ -11,20 +11,25 @@
#define SETTINGS_H_
#include <stdint.h>
#include "stm32f10x_flash.h"
#define SETTINGSVERSION 0x02 /*Change this if you change the struct below to prevent people getting out of sync*/
#define SETTINGSOPTIONSCOUNT 5 /*Number of settings in the settings menu*/
#define SETTINGSVERSION 0x03 /*Change this if you change the struct below to prevent people getting out of sync*/
#define SETTINGSOPTIONSCOUNT 6 /*Number of settings in the settings menu*/
#define MOTION_HIGH (0x00)
#define MOTION_MED (0x10)
#define MOTION_LOW (0x20)
/*
* This struct must be a multiple of 2 bytes as it is saved / restored from flash in uint16_t chunks
*/
struct {
uint32_t SolderingTemp; //current setpoint for the iron
uint32_t SleepTemp; //temp to drop to in sleep
uint8_t version; //Used to track if a reset is needed on firmware upgrade
uint8_t SleepTime; //minutes timeout to sleep
uint8_t cutoutVoltage; //The voltage we cutout at for undervoltage
uint8_t movementEnabled; //If movement is enabled
uint8_t displayTempInF; //If we need to convert the C reading to F
uint8_t flipDisplay; //If true we want to invert the display for lefties
uint32_t SolderingTemp; //current setpoint for the iron
uint32_t SleepTemp; //temp to drop to in sleep
uint8_t version; //Used to track if a reset is needed on firmware upgrade
uint8_t SleepTime; //minutes timeout to sleep
uint8_t cutoutVoltage:5; //The voltage we cutout at for undervoltage
uint8_t movementEnabled:1; //If movement is enabled
uint8_t displayTempInF:1; //If we need to convert the C reading to F
uint8_t flipDisplay:1; //If true we want to invert the display for lefties
uint8_t sensitivity:7; //Sensitivity of accelerometer
uint16_t tempCalibration; //Temperature calibration value
} systemSettings;
void saveSettings();

View File

@@ -105,16 +105,30 @@ uint16_t Get_ADC1Value(uint8_t i) {
}
//This returns the calibrated temperature reading of the iron temp
//inputs : calibration value / wether to take a new reading or not
uint16_t readIronTemp(uint16_t calibration_temp, uint8_t read) {
uint16_t readIronTemp(uint16_t calibration_temp, uint8_t read,
uint16_t setPointTemp) {
static uint16_t calTemp = 0;
static uint16_t lastVal = 0;
static uint16_t lastSetTemp;
if(setPointTemp!=0xFFFF)
lastSetTemp = setPointTemp;
if (calibration_temp != 0)
calTemp = calibration_temp;
if (read) {
lastVal = (readTipTemp() * 1000 + 806 * readSensorTemp()
- calTemp * 1000) / 806;
int16_t compensation = 80 + 150 * (lastSetTemp - 1000) / 3000;
int16_t tipTemp = readTipTemp();
int16_t ColdJTemp = readSensorTemp();
if (lastSetTemp == 1000)
compensation -= 10;
if (lastSetTemp != 0) {
if (tipTemp > (compensation + calTemp))
tipTemp -= compensation;
}
if (ColdJTemp > 400)
ColdJTemp = 400;
lastVal = (tipTemp * 1000 + 807 * ColdJTemp - calTemp * 1000) / 807;
}

View File

@@ -53,7 +53,7 @@ void TIM3_IRQHandler(void) {
//used for buttons and movement
void EXTI9_5_IRQHandler(void) {
//we are interested in line 9 and line 6 for buttons
//Lien 5 == movement
//Line 5 == movement
if (EXTI_GetITStatus(EXTI_Line9) != RESET) {
if (GPIO_ReadInputDataBit(GPIOA, KEY_A) == SET)
keyState &= ~(BUT_A);

View File

@@ -29,15 +29,15 @@ uint8_t I2C_RegisterRead(uint8_t reg) {
return tx_data[0];
}
void StartUp_Accelerometer(void) {
void StartUp_Accelerometer(uint8_t sensitivity) {
I2C_RegisterWrite(CTRL_REG2, 0); //Normal mode
I2C_RegisterWrite( CTRL_REG2, 0x40); // Reset all registers to POR values
delayMs(2); // ~1ms delay
I2C_RegisterWrite(FF_MT_CFG_REG, 0x78); // Enable motion detection for X and Y axis, latch enabled
I2C_RegisterWrite(FF_MT_THS_REG, 0x0F); // Set threshold
I2C_RegisterWrite(FF_MT_THS_REG, sensitivity|0x0F); // Set threshold
I2C_RegisterWrite(FF_MT_COUNT_REG, 0x01); // Set debounce to 100ms
I2C_RegisterWrite( CTRL_REG4, 0x04); // Enable motion interrupt
I2C_RegisterWrite( CTRL_REG5, 0x04);// Route motion interrupts to INT1 ->PB5 ->EXTI
I2C_RegisterWrite( CTRL_REG5, 0x04);// Route motion interrupts to INT1 ->PB5 ->EXTI5
I2C_RegisterWrite( CTRL_REG1, 0x19); // ODR=100 Hz, Active mode
}

View File

@@ -14,29 +14,30 @@ void setup();
int main(void) {
setup();/*Setup the system*/
while (1) {
Clear_Watchdog(); //reset the Watchdog timer
Clear_Watchdog(); //reset the Watch dog timer
ProcessUI();
DrawUI();
delayMs(50); //Slow the system down a little bit
}
}
void setup() {
RCC_Config(); //setup system clock
NVIC_Config(0x4000); //this shifts the NVIC table to be offset, for the usb bootloader's size
GPIO_Config(); //setup all the GPIO pins
Init_EXTI(); //init the EXTI inputs
Init_Timer3(); //Used for the soldering iron tip
Adc_Init(); //init adc and dma
I2C_Configuration(); //Start the I2C hardware
GPIO_Init_OLED(); //Init the GPIO ports for the OLED
StartUp_Accelerometer(); //start the accelerometer
Init_Oled(); //init the OLED display
setupPID(); //init the PID values
readIronTemp(239, 0); //load the default calibration value
restoreSettings(); //Load settings
if (systemSettings.flipDisplay)
Oled_DisplayFlip();
OLED_DrawString("VER 1.01",8);
delayMs(800);
Start_Watchdog(1000); //start the system watchdog as 1 seconds timeout
RCC_Config(); //setup system clock
NVIC_Config(0x4000); //this shifts the NVIC table to be offset, for the usb bootloader's size
GPIO_Config(); //setup all the GPIO pins
Init_EXTI(); //Init the EXTI inputs
Init_Timer3(); //Used for the soldering iron tip
Adc_Init(); //Init adc and DMA
I2C_Configuration(); //Start the I2C hardware
GPIO_Init_OLED(); //Init the GPIO ports for the OLED
restoreSettings(); //Load settings
StartUp_Accelerometer(systemSettings.sensitivity); //start the accelerometer
setupPID(); //Init the PID values
readIronTemp(systemSettings.tempCalibration, 0,0); //load the default calibration value
Init_Oled(systemSettings.flipDisplay); //Init the OLED display
OLED_DrawString("VER 1.04", 8); //
delayMs(800); //Pause to show version number
Start_Watchdog(1000); //start the system watch dog as 1 second timeout
}

View File

@@ -5,43 +5,41 @@
* Author: Ralim <ralim@ralimtek.com>
*/
#include "Modes.h"
uint8_t tempCalStatus = 0;
//This does the required processing and state changes
void ProcessUI() {
uint8_t Buttons = getButtons(); //read the buttons status
static uint32_t lastModeChange = 0;
if (millis() - getLastButtonPress() < 200)
if (millis() - getLastButtonPress() < 30)
Buttons = 0;
else if (Buttons != 0) {
resetLastButtonPress();
resetButtons();
}
//rough prevention for de-bouncing and allocates settling time
switch (operatingMode) {
case STARTUP:
if ((millis() - getLastButtonPress() > 1000)) {
if (Buttons & BUT_A) {
//A key pressed so we are moving to soldering mode
operatingMode = SOLDERING;
resetLastButtonPress();
resetButtons();
} else if (Buttons & BUT_B) {
//B Button was pressed so we are moving to the Settings menu
operatingMode = SETTINGS;
resetLastButtonPress();
resetButtons();
}
if (Buttons == (BUT_A | BUT_B)) {
operatingMode = THERMOMETER;
} else if (Buttons == BUT_A) {
//A key pressed so we are moving to soldering mode
operatingMode = SOLDERING;
} else if (Buttons == BUT_B) {
//B Button was pressed so we are moving to the Settings menu
operatingMode = SETTINGS;
}
//Nothing else to check here
break;
case SOLDERING:
//We need to check the buttons if we need to jump out
if (Buttons & BUT_A) {
//A key pressed so we are moving to temp set
if (Buttons == BUT_A || Buttons == BUT_B) {
//A or B key pressed so we are moving to temp set
operatingMode = TEMP_ADJ;
resetLastButtonPress();
resetButtons();
} else if (Buttons & BUT_B) {
//B Button was pressed so we are moving back to idle
} else if (Buttons == (BUT_A | BUT_B)) {
//Both buttons were pressed, exit back to the cooling screen
operatingMode = COOLING;
resetLastButtonPress();
resetButtons();
} else {
//We need to check the timer for movement in case we need to goto idle
if (systemSettings.movementEnabled)
@@ -56,32 +54,29 @@ void ProcessUI() {
uint16_t voltage = readDCVoltage(); //get X10 voltage
if ((voltage / 10) < systemSettings.cutoutVoltage) {
operatingMode = UVLOWARN;
resetLastButtonPress();
resetButtons();
lastModeChange = millis();
}
//If no buttons pushed we need to perform the PID loop for the iron temp
//Update the PID Loop
int32_t newOutput = computePID(systemSettings.SolderingTemp);
setIronTimer(newOutput);
}
break;
case TEMP_ADJ:
if (Buttons & BUT_A) {
if (Buttons == BUT_A) {
//A key pressed so we are moving down in temp
resetLastButtonPress();
if (systemSettings.SolderingTemp > 1000)
systemSettings.SolderingTemp -= 100;
} else if (Buttons & BUT_B) {
} else if (Buttons == BUT_B) {
//B key pressed so we are moving up in temp
resetLastButtonPress();
if (systemSettings.SolderingTemp < 4500)
systemSettings.SolderingTemp += 100;
} else {
//we check the timeout for how long the buttons have not been pushed
//if idle for > 3 seconds then we return to soldering
if (millis() - getLastButtonPress() > 3000) {
//Or if both buttons pressed
if ((millis() - getLastButtonPress() > 2000)
|| Buttons == (BUT_A | BUT_B)) {
operatingMode = SOLDERING;
saveSettings();
}
@@ -90,11 +85,8 @@ void ProcessUI() {
case SETTINGS:
//Settings is the mode with the most logic
//Here we are in the menu so we need to increment through the sub menus / increase the value
if (millis() - getLastButtonPress() < 300)
return;
if (Buttons & BUT_A) {
resetLastButtonPress();
//A key iterates through the menu
if (settingsPage == SETTINGSOPTIONSCOUNT) {
//Roll off the end
@@ -133,6 +125,12 @@ void ProcessUI() {
break;
case LEFTY:
systemSettings.flipDisplay = !systemSettings.flipDisplay;
break;
case MOTIONSENSITIVITY:
systemSettings.sensitivity += 0x10;
if (systemSettings.sensitivity > 0x20)
systemSettings.sensitivity = 0; //reset to high on wrap
break;
default:
break;
@@ -144,14 +142,10 @@ void ProcessUI() {
if (Buttons & BUT_A) {
//A Button was pressed so we are moving back to soldering
operatingMode = SOLDERING;
resetLastButtonPress();
resetButtons();
return;
} else if (Buttons & BUT_B) {
//B Button was pressed so we are moving back to soldering
operatingMode = SOLDERING;
resetLastButtonPress();
resetButtons();
return;
} else if (systemSettings.movementEnabled)
if (millis() - getLastMovement() < 1000) {//moved in the last second
@@ -160,28 +154,17 @@ void ProcessUI() {
}
//else if nothing has been pushed we need to compute the PID to keep the iron at the sleep temp
int32_t newOutput = computePID(systemSettings.SleepTemp);
setIronTimer(newOutput);
break;
case COOLING: {
setIronTimer(0); //turn off heating
//This mode warns the user the iron is still cooling down
uint16_t temp = readIronTemp(0, 1); //take a new reading as the heater code is not taking new readings
if (temp < 500) { //if the temp is < 50C then we can go back to IDLE
uint16_t temp = readIronTemp(0, 1, 0xFFFF); //take a new reading as the heater code is not taking new readings
if (temp < 400) { //if the temp is < 40C then we can go back to IDLE
operatingMode = STARTUP;
} else if (Buttons & (BUT_A | BUT_B)) { //we check if the user has pushed a button to ack
//Either button was pushed
operatingMode = STARTUP;
resetLastButtonPress();
resetButtons();
} else { //we check if the user has pushed a button to ack
if ((millis() - getLastButtonPress() > 200)
&& (millis() - getLastButtonPress() < 2000)) {
if (getButtons() && (BUT_A | BUT_B)) {
//A button was pushed
operatingMode = STARTUP;
resetLastButtonPress();
resetButtons();
}
}
}
}
break;
@@ -192,6 +175,57 @@ void ProcessUI() {
operatingMode = STARTUP; //jump back to idle mode
}
break;
case THERMOMETER: {
//This lets the user check the tip temp without heating the iron.. And eventually calibration will be added here
if (Buttons == BUT_A) {
//Single button press, cycle over to the DC display
operatingMode = DCINDISP;
} else if (Buttons == BUT_B) {
tempCalStatus = 0;
operatingMode = TEMPCAL;
} else if (Buttons == (BUT_A | BUT_B)) {
//If the user is holding both button, exit the screen
operatingMode = STARTUP;
}
}
break;
case DCINDISP: {
//This lets the user check the input voltage
if (Buttons == BUT_A) {
//Single button press, cycle over to the temp display
operatingMode = THERMOMETER;
} else if (Buttons == (BUT_A | BUT_B)) {
//If the user is holding both button, exit the screen
operatingMode = STARTUP;
}
}
break;
case TEMPCAL: {
if (Buttons == BUT_B) {
//Single button press, cycle over to the DC IN
operatingMode = THERMOMETER;
} else if (Buttons == BUT_A) {
//Try and calibrate
if (tempCalStatus == 0) {
if ((readTipTemp() < 300) && (readSensorTemp() < 300)) {
tempCalStatus = 1;
systemSettings.tempCalibration = readTipTemp();
saveSettings();
} else {
tempCalStatus = 2;
}
}
} else if (Buttons == (BUT_A | BUT_B)) {
//If the user is holding both button, exit the screen
operatingMode = STARTUP;
}
}
break;
default:
break;
}
@@ -202,6 +236,8 @@ void ProcessUI() {
void drawTemp(uint16_t temp, uint8_t x) {
if (systemSettings.displayTempInF)
temp = (temp * 9 + 1600) / 5;/*Convert to F -> T*(9/5)+32*/
if (temp % 10 > 5)
temp += 10;//round up
OLED_DrawThreeNumber(temp / 10, x);
}
@@ -209,7 +245,7 @@ void drawTemp(uint16_t temp, uint8_t x) {
* Performs all the OLED drawing for the current operating mode
*/
void DrawUI() {
uint16_t temp = readIronTemp(0, 0);
uint16_t temp = readIronTemp(0, 0, 0xFFFF);
switch (operatingMode) {
case STARTUP:
//We are chilling in the idle mode
@@ -220,7 +256,8 @@ void DrawUI() {
Oled_DisplayOff();
} else {
Oled_DisplayOn();
OLED_DrawString(" IDLE ", 8); //write the word IDLE
//OLED_DrawString(" IDLE ", 8); //write the word IDLE
OLED_DrawIDLELogo();
}
break;
case SOLDERING:
@@ -229,7 +266,7 @@ void DrawUI() {
if (getIronTimer() == 0) {
OLED_DrawChar('C', 5);
} else {
if (getIronTimer() < 500) {
if (getIronTimer() < 900) {
OLED_DrawChar(' ', 5);
} else { //we are heating
OLED_DrawChar('H', 5);
@@ -292,6 +329,23 @@ void DrawUI() {
else
OLED_DrawString("FLPDSP F", 8);
break;
case MOTIONSENSITIVITY:
switch (systemSettings.sensitivity) {
case MOTION_HIGH:
OLED_DrawString("SENSE H ", 8);
break;
case MOTION_MED:
OLED_DrawString("SENSE M ", 8);
break;
case MOTION_LOW:
OLED_DrawString("SENSE L ", 8);
break;
default:
OLED_DrawString("SENSE ", 8);
break;
}
break;
default:
break;
}
@@ -300,15 +354,46 @@ void DrawUI() {
//The iron is in sleep temp mode
//Draw in temp and sleep
OLED_DrawString("SLP", 3);
drawTemp(temp, 3);
drawTemp(temp, 4);
break;
case COOLING:
//We are warning the user the tip is cooling
OLED_DrawString("COOL", 3);
drawTemp(temp, 4);
OLED_DrawString("COOL", 4);
drawTemp(temp, 5);
break;
case UVLOWARN:
OLED_DrawString("LOW VOLT", 8);
break;
case THERMOMETER:
temp = readIronTemp(0, 1, 0xFFFF); //Force a reading as heater is off
OLED_DrawString("TEMP ", 5);//extra one to it clears the leftover 'L' from IDLE
drawTemp(temp, 5);
break;
case DCINDISP: {
uint16_t voltage = readDCVoltage(); //get X10 voltage
OLED_DrawString("IN", 2);
OLED_DrawChar((voltage / 100) % 10, 2);
voltage -= (voltage / 100) * 100;
OLED_DrawChar((voltage / 10) % 10, 3);
voltage -= (voltage / 10) * 10;
OLED_DrawChar('.', 4);
OLED_DrawChar(voltage % 10, 5);
OLED_DrawChar('V', 6);
OLED_DrawChar(' ', 7);
}
break;
case TEMPCAL: {
if (tempCalStatus == 0) {
OLED_DrawString("CAL TEMP", 8);
} else if (tempCalStatus == 1) {
OLED_DrawString("CAL OK ", 8);
} else if (tempCalStatus == 2) {
OLED_DrawString("CAL FAIL", 8);
}
}
break;
default:
break;

View File

@@ -13,22 +13,22 @@
#include "I2C.h"
#include "Font.h"
u8 displayOffset = 32;
int8_t displayOffset = 32;
/*Setup params for the OLED screen*/
/*http://www.displayfuture.com/Display/datasheet/controller/SSD1307.pdf*/
/*All commands are prefixed with 0x80*/
u8 OLED_Setup_Array[46] = { 0x80, 0xAE,/*Display off*/
0x80, 0xD5,/*Set display clock divide ratio / osc freq*/
0x80, 0b01010001,/**/
0x80, 0x52,/*Unknown*/
0x80, 0xA8,/*Set Multiplex Ratio*/
0x80, 16, /*16 == max brightness,39==dimmest*/
0x80, 0x0F, /*16 == max brightness,39==dimmest*/
0x80, 0xC0,/*Set COM Scan direction*/
0x80, 0xD3,/*Set Display offset*/
0x80, 0x00,/*0 Offset*/
0x80, 0x40,/*Set Display start line to 0*/
0x80, 0xA0,/*Set Segment remap to normal*/
0x80, 0x8D,/*Unknown*/
0x80, 0x14,/**/
0x80, 0x14,/*Unknown*/
0x80, 0xDA,/*Set VCOM Pins hardware config*/
0x80, 0x02,/*Combination 2*/
0x80, 0x81,/*Contrast*/
@@ -36,7 +36,7 @@ u8 OLED_Setup_Array[46] = { 0x80, 0xAE,/*Display off*/
0x80, 0xD9,/*Set pre-charge period*/
0x80, 0xF1,/**/
0x80, 0xDB,/*Adjust VCOMH regulator ouput*/
0x80, 0x30,/**/
0x80, 0x30,/*Unknown*/
0x80, 0xA4,/*Enable the display GDDR*/
0x80, 0XA6,/*Normal display*/
0x80, 0xAF /*Dispaly on*/
@@ -69,7 +69,7 @@ void Oled_DisplayFlip() {
I2C_PageWrite(data, 2, DEVICEADDR_OLED);
data[1] = 0xA1;
I2C_PageWrite(data, 2, DEVICEADDR_OLED);
displayOffset=0;
displayOffset = 0;
}
/*
@@ -79,10 +79,10 @@ void Oled_DisplayFlip() {
*/
u8* Data_Command(u8 length, u8* data) {
int i;
u8 tx_data[128];
u8 tx_data[129];
//here are are inserting the data write command at the beginning
tx_data[0] = 0x40;
length += 1;
length++;
for (i = 1; i < length; i++) //Loop through the array of data
tx_data[i] = *data++;
I2C_PageWrite(tx_data, length, DEVICEADDR_OLED); //write out the buffer
@@ -96,7 +96,7 @@ u8* Data_Command(u8 length, u8* data) {
void Set_ShowPos(u8 x, u8 y) {
u8 pos_param[8] = { 0x80, 0xB0, 0x80, 0x21, 0x80, 0x00, 0x80, 0x7F };
//page 0, start add = x(below) through to 0x7F (aka 127)
pos_param[5] = x + displayOffset;/*Display offset ==0 for Lefty, == 32 fo righty*/
pos_param[5] = x + displayOffset;/*Display offset ==0 for Lefty, == 32 for righty*/
pos_param[1] += y;
I2C_PageWrite(pos_param, 8, DEVICEADDR_OLED);
}
@@ -105,7 +105,7 @@ void Set_ShowPos(u8 x, u8 y) {
Function:Oled_DrawArea
Description:
Inputs:(x,y) start point, (width,height) of enclosing rect, pointer to data
Output: last byte written out
Output: pointer to the last byte written out
*******************************************************************************/
u8* Oled_DrawArea(u8 x0, u8 y0, u8 wide, u8 high, u8* ptr) {
u8 m, n, y;
@@ -142,16 +142,21 @@ void GPIO_Init_OLED(void) {
}
/*******************************************************************************
Function: Init_Oled
Description: Initalizes the Oled screen
Description: Initializes the Oled screen
*******************************************************************************/
void Init_Oled(void) {
void Init_Oled(uint8_t leftHanded) {
u8 param_len;
OLED_RST();
delayMs(2);
delayMs(5);
OLED_ACT(); //Toggling reset to reset the oled
delayMs(2);
delayMs(5);
param_len = 46;
if (leftHanded) {
OLED_Setup_Array[11] = 0xC8;
OLED_Setup_Array[19] = 0xA1;
displayOffset = 0;
}
I2C_PageWrite((u8 *) OLED_Setup_Array, param_len, DEVICEADDR_OLED);
}
@@ -161,7 +166,7 @@ void Init_Oled(void) {
*******************************************************************************/
void Clear_Screen(void) {
u8 tx_data[128];
memset(&tx_data[0], 0, 128);
memset(tx_data, 0, 128);
for (u8 i = 0; i < 2; i++) {
Oled_DrawArea(0, i * 8, 128, 8, tx_data);
}
@@ -196,8 +201,7 @@ void OLED_DrawChar(char c, uint8_t x) {
ptr += (37) * (FONT_WIDTH * 2);
} else if (c == '>') {
ptr += (38) * (FONT_WIDTH * 2);
}else if (c=='.')
{
} else if (c == '.') {
ptr += (39) * (FONT_WIDTH * 2);
}
@@ -230,3 +234,23 @@ void OLED_DrawFourNumber(uint16_t in, uint8_t x) {
OLED_DrawChar((in / 10) % 10, x + 2);
OLED_DrawChar(in % 10, x + 3);
}
void OLED_DrawIDLELogo() {
static uint8_t drawAttempt = 0;
drawAttempt++;
if (drawAttempt & 0x80) {
if (drawAttempt & 0x08)
Oled_DrawArea(0, 0, 96, 8, (u8*) Iron_RightArrow_UP);
else
Oled_DrawArea(0, 0, 96, 8, (u8*) Iron_RightArrow_DOWN);
Oled_DrawArea(0, 8, 96, 8, (u8*) Iron_Base);
} else {
if (drawAttempt & 0x08)
Oled_DrawArea(0, 0, 96, 8, (u8*) Iron_LeftArrow_UP);
else
Oled_DrawArea(0, 0, 96, 8, (u8*) Iron_LeftArrow_DOWN);
Oled_DrawArea(0, 8, 96, 8, (u8*) Iron_Base);
}
}

View File

@@ -12,7 +12,7 @@
int32_t computePID(uint16_t setpoint) {
int32_t ITerm = 0;
static int16_t lastReading = 0;
uint16_t currentReading = readIronTemp(0, 1); //get the current temp of the iron
uint16_t currentReading = readIronTemp(0, 1,setpoint); //get the current temp of the iron
int16_t error = (int16_t) setpoint - (int16_t) currentReading; //calculate the error term
ITerm += (pidSettings.ki * error);
if (ITerm > MAXPIDOUTPUT)
@@ -34,7 +34,7 @@ int32_t computePID(uint16_t setpoint) {
}
/*Sets up the pid values*/
void setupPID(void) {
pidSettings.kp = 22;
pidSettings.kp = 25;
pidSettings.ki = 7;
pidSettings.kd = 2;

View File

@@ -49,5 +49,8 @@ void resetSettings() {
systemSettings.version = SETTINGSVERSION; //Store the version number to allow for easier upgrades
systemSettings.displayTempInF =0; //default to C
systemSettings.flipDisplay=0; //Default to right handed mode
systemSettings.sensitivity=0x00; //Default high sensitivity
systemSettings.tempCalibration=239; //Default to their calibration value
}