Changeset - 425d70b8073e
[Not reviewed]
Merge cortex-f0
0 3 0
Ethan Zonca - 10 years ago 2015-01-02 23:41:03
ez@ethanzonca.com
Merge in multiple setpoints, fahrenheit support, tc error page to f0 branch
3 files changed with 157 insertions and 11 deletions:
0 comments (0 inline, 0 general)
Makefile
Show inline comments
 
@@ -76,25 +76,25 @@ SRC+=usb_prop.c
 
SRC+=usb_pwr.c
 

	
 
CDEFS=-DUSE_STDPERIPH_DRIVER
 
CDEFS+=-DSTM32F0XX
 
CDEFS+=-DMANGUSTA_DISCOVERY
 
#CDEFS+=-DUSE_USB_OTG_FS
 

	
 
# EMZ FIXME
 
CDEFS+=-DHSE_VALUE=8000000
 

	
 

	
 
#EMZ Optimized: 
 
MCUFLAGS=-mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections 
 
MCUFLAGS=-mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections -mfloat-abi=soft
 

	
 
# Default:  MCUFLAGS=-mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections
 

	
 
#MCUFLAGS=-mcpu=cortex-m4 -mthumb -mlittle-endian -mfpu=fpa -mfloat-abi=hard -mthumb-interwork
 
#MCUFLAGS=-mcpu=cortex-m4 -mfpu=vfpv4-sp-d16 -mfloat-abi=hard
 
COMMONFLAGS=-O$(OPTLVL) -g -Wall
 
CFLAGS=$(COMMONFLAGS) $(MCUFLAGS) $(INCLUDE) $(CDEFS)
 

	
 
LDLIBS=
 
LDFLAGS=$(COMMONFLAGS) -fno-exceptions -ffunction-sections -fdata-sections \
 
        -nostartfiles -Wl,--gc-sections,-T$(LINKER_SCRIPT)
 

	
eeprom_min.h
Show inline comments
 
@@ -4,20 +4,22 @@
 
#define EEPROM_BASE_ADDR    0x08080000    
 
#define EEPROM_BYTE_SIZE    0x0FFF  
 

	
 
#define EEPROM_ADDR_WINDUP_GUARD 	0x001C
 
#define EEPROM_ADDR_BOOTTOBREW		0x0020
 
#define EEPROM_ADDR_K_P			0x0024
 
#define EEPROM_ADDR_K_I			0x0028
 
#define EEPROM_ADDR_K_D			0x002C
 

	
 
#define EEPROM_ADDR_BREWTEMP		0x0030
 
#define EEPROM_ADDR_STEAMTEMP		0x0034
 

	
 
#define EEPROM_ADDR_UNITS		0x0038
 

	
 

	
 
void Minimal_EEPROM_Unlock(void);
 
void Minimal_EEPROM_Lock(void);
 
FLASH_Status Minimal_FLASH_GetStatus(void);
 
FLASH_Status Minimal_FLASH_WaitForLastOperation(uint32_t Timeout);
 
void Minimal_EEPROM_ProgramWord(uint32_t Address, uint32_t Data);
 

	
 
#endif
main.c
Show inline comments
 
@@ -14,51 +14,63 @@
 
#include "stringhelpers.h"
 
 
// TODO: Grab buttonpresses with interrupts
 
 
// USB Supporting Vars
 
extern __IO uint8_t Receive_Buffer[64];
 
extern __IO  uint32_t Receive_length ;
 
extern __IO  uint32_t length ;
 
uint8_t Send_Buffer[64];
 
uint32_t packet_sent=1;
 
uint32_t packet_receive=1;
 
 
enum tempunits {
 
    TEMP_UNITS_CELSIUS = 0,
 
    TEMP_UNITS_FAHRENHEIT,
 
};
 
 
// Globalish setting vars
 
uint8_t boottobrew = 0;
 
uint8_t temp_units = TEMP_UNITS_CELSIUS;
 
uint16_t windup_guard = 1;
 
uint16_t k_p = 1;
 
uint16_t k_i = 1;
 
uint16_t k_d = 1;
 
 
uint8_t ignore_tc_error  = 0;
 
 
// ISR ticks var
 
volatile uint32_t ticks = 0;
 
 
int16_t setpoint_brew = 0;
 
int16_t setpoint_steam = 0;
 
 
// State definition
 
enum state {
 
    STATE_IDLE = 0,
 
 
    STATE_SETP,
 
    STATE_SETI,
 
    STATE_SETD,
 
    STATE_SETSTEPS,
 
    STATE_SETWINDUP,
 
    STATE_SETBOOTTOBREW,
 
    STATE_SETUNITS,
 
 
    STATE_PREHEAT_BREW,
 
    STATE_MAINTAIN_BREW,
 
    STATE_PREHEAT_STEAM,
 
    STATE_MAINTAIN_STEAM,
 
 
    STATE_TC_ERROR
 
};
 
 
uint8_t state = STATE_IDLE;
 
 
static __IO uint32_t TimingDelay;
 
 
// Move to header file
 
void process();
 
void machine();
 
 
void restore_settings();
 
void save_settings();
 
@@ -121,60 +133,81 @@ int main(void)
 
    // Main loop
 
    while(1)
 
    {
 
        // Process sensor inputs
 
        process();
 
 
        // Run state machine
 
        machine(); 
 
    }
 
}
 
 
// Read temperature and update global temp vars
 
int16_t temp = 0;
 
int32_t temp = 0;
 
uint8_t temp_frac = 0;
 
uint8_t state_resume = 0;
 
 
void update_temp() {
 
    // Assert CS
 
    GPIO_ResetBits(MAX_CS);
 
    delay(1);
 
 
    // This may not clock at all... might need to send 16 bits first
 
    SPI_I2S_SendData(SPI2, 0xAAAA); // send dummy data
 
    //SPI_I2S_SendData(SPI2, 0xAA); // send dummy data
 
    uint16_t temp_pre = SPI_I2S_ReceiveData(SPI2);
 
 
    if(temp_pre & 0b0000000000000010) {
 
        ssd1306_DrawString("Fatal Error", 2, 35);
 
        ssd1306_DrawString("Fatal Error", 3, 35);
 
        state = STATE_TC_ERROR;
 
    }
 
    else if(temp_pre & 0b0000000000000001) {
 
        ssd1306_DrawString("Error: No TC", 2, 40);
 
    else if(temp_pre & 0b0000000000000001 && !ignore_tc_error) {
 
        state_resume = state;
 
        state = STATE_TC_ERROR;
 
        temp = 0;
 
        temp_frac = 0;
 
    }
 
    else 
 
    {
 
        if(state == STATE_TC_ERROR)
 
        {
 
            state = state_resume;
 
            ssd1306_clearscreen();
 
        }
 
 
        uint8_t sign = temp >> 15;// top bit is sign
 
 
        temp_pre = temp_pre >> 2; // Drop 2 lowest bits
 
        temp_frac = temp_pre & 0b11; // get fractional part
 
        temp_frac *= 25; // each bit is .25 a degree, up to fixed point
 
        temp_pre = temp_pre >> 2; // Drop 2 fractional bits 
 
 
        if(sign) {
 
            temp = -temp_pre;
 
        }
 
        else {
 
            temp = temp_pre;
 
        }
 
 
        if(temp_units == TEMP_UNITS_FAHRENHEIT) {
 
            temp *= 9; // fixed point mul by 1.8
 
            temp /= 5;
 
            temp += 32;
 
 
            temp_frac *= 9;
 
            temp_frac /= 5;
 
            temp_frac += 32;
 
            temp += temp_frac/100; // add overflow to above
 
            temp_frac %= 100;
 
        }
 
    }
 
 
    // Deassert CS
 
    delay(1);
 
    GPIO_SetBits(MAX_CS);
 
}
 
 
 
// PID implementation
 
// TODO: Make struct that has the last_temp and i_state in it, pass by ref. Make struct that has other input values maybe.
 
int16_t last_pid_temp = 0;
 
uint8_t last_pid_temp_frac = 0;
 
@@ -307,24 +340,25 @@ uint8_t sw_right_last = 0;
 
#define SW_LEFT_PRESSED (sw_left_last == 0 && sw_left == 1)
 
#define SW_RIGHT_PRESSED (sw_right_last == 0 && sw_right == 1)
 
 
void save_settings()
 
{
 
   Minimal_EEPROM_Unlock();
 
    // Try programming a word at an address divisible by 4
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_BOOTTOBREW, boottobrew);
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_WINDUP_GUARD, windup_guard);
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_K_P, k_p);
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_K_I, k_i);
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_K_D, k_d);
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_UNITS, temp_units);
 
    Minimal_EEPROM_Lock();
 
}
 
 
void save_setpoints()
 
{
 
 
    Minimal_EEPROM_Unlock();
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_BREWTEMP, setpoint_brew);
 
    Minimal_EEPROM_ProgramWord(EEPROM_BASE_ADDR + EEPROM_ADDR_STEAMTEMP, setpoint_steam); 
 
    Minimal_EEPROM_Lock();
 
}
 
 
@@ -344,30 +378,46 @@ void restore_settings()
 
 
    while(Minimal_FLASH_GetStatus()==FLASH_BUSY);
 
    k_i = (*(__IO uint32_t*)(EEPROM_BASE_ADDR + EEPROM_ADDR_K_I));
 
 
    while(Minimal_FLASH_GetStatus()==FLASH_BUSY);
 
    k_d = (*(__IO uint32_t*)(EEPROM_BASE_ADDR + EEPROM_ADDR_K_D));
 
    
 
    while(Minimal_FLASH_GetStatus()==FLASH_BUSY);
 
    setpoint_brew = (*(__IO uint32_t*)(EEPROM_BASE_ADDR + EEPROM_ADDR_BREWTEMP));
 
 
    while(Minimal_FLASH_GetStatus()==FLASH_BUSY);
 
    setpoint_steam = (*(__IO uint32_t*)(EEPROM_BASE_ADDR + EEPROM_ADDR_STEAMTEMP));    
 
    
 
    while(Minimal_FLASH_GetStatus()==FLASH_BUSY);
 
    temp_units = (*(__IO uint32_t*)(EEPROM_BASE_ADDR + EEPROM_ADDR_UNITS));    
 
 
    Minimal_EEPROM_Lock();
 
}
 
 
int16_t last_temp = 21245;
 
 
 
///////////////////////////////////////////////////////////////////////////////////////
 
/// freaking multiple setpoint support ///
 
uint8_t step_duration[10] = {0,0,0,0,0,0,0,0,0,0};
 
int16_t step_setpoint[10] = {0,0,0,0,0,0,0,0,0,0};
 
uint8_t final_setpoint = 0;
 
 
// Multiple screens to set setpoint and duration on each screen
 
// press center to go to the next one, and press left or right or something to confirm
 
 
// When executing, complete on time AND(?) temperature. Maybe allow switching to OR via settings
 
 
////////////////////////////////////////////////////////////////////////////////////////////////
 
 
void machine()
 
{
 
    uint8_t last_state = state;
 
    
 
    uint8_t temp_changed = temp != last_temp;
 
    last_temp = temp;
 
 
    uint8_t sw_btn = !GPIO_ReadInputDataBit(SW_BTN);
 
    uint8_t sw_up = !GPIO_ReadInputDataBit(SW_UP);
 
    uint8_t sw_down = !GPIO_ReadInputDataBit(SW_DOWN);
 
    uint8_t sw_left = !GPIO_ReadInputDataBit(SW_LEFT);
 
    uint8_t sw_right = !GPIO_ReadInputDataBit(SW_RIGHT);
 
@@ -386,25 +436,25 @@ void machine()
 
                char tempstr[6];
 
                itoa_fp(temp, temp_frac, tempstr);
 
                ssd1306_DrawString("Temp: ", 3, 40);
 
                ssd1306_DrawString("    ", 3, 72);
 
                ssd1306_DrawString(tempstr, 3, 72);
 
            }
 
 
            ssd1306_drawlogo();
 
 
            switch(goto_mode) {
 
                case 2:
 
                {
 
                    ssd1306_DrawString("-> brew     ", 1, 40);
 
                    ssd1306_DrawString("-> heat     ", 1, 40);
 
                } break;
 
 
                case 1:
 
                {
 
                    ssd1306_DrawString("-> setup    ", 1, 40);
 
                } break;
 
 
                case 0:
 
                {
 
                    ssd1306_DrawString("-> reset    ", 1, 40);
 
                } break;
 
            }
 
@@ -516,24 +566,63 @@ void machine()
 
            if(SW_BTN_PRESSED) {
 
                state = STATE_SETWINDUP;
 
            }
 
            else {
 
                user_input(&k_d);
 
            }
 
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 
 
        case STATE_SETSTEPS:
 
        {
 
            // Write text to OLED
 
            // [ step #1:: Duration: ### ]
 
            // [           Setpoint: ### ]
 
            char tempstr[6];
 
 
            itoa(final_setpoint, tempstr);
 
            ssd1306_DrawString("Step #", 0, 0);
 
            ssd1306_DrawString(tempstr, 0, 40);
 
 
            ssd1306_DrawString("Duration: ", 0, 5);
 
            itoa(step_duration[final_setpoint], tempstr);
 
            ssd1306_DrawString(tempstr, 0, 70);
 
 
            ssd1306_DrawString("Setpoint: ", 0, 0);
 
            itoa(step_setpoint[final_setpoint], tempstr);
 
            ssd1306_DrawString(tempstr, 0, 70);
 
 
            ssd1306_DrawString("Press to accept", 3, 40);
 
            
 
            // Button handler - TODO: increment max_step if pressed
 
            // return and go to next state otherwise
 
            if(SW_BTN_PRESSED) {
 
                state = STATE_SETSTEPS;
 
                final_setpoint++;
 
            }
 
        //    else if(SW_LEFT_PRESSED) {
 
        //        state++; // go to next state or something
 
        //    }
 
            else {
 
                user_input(&k_p);
 
            }
 
 
            // Event Handler
 
            // N/A
 
 
        } break;
 
 
        case STATE_SETWINDUP:
 
        {
 
            // Write text to OLED
 
            // [ therm :: set windup ]
 
            // [ g = 12         ]
 
            ssd1306_DrawString("Windup Guard", 0, 40);
 
            ssd1306_drawlogo();
 
 
            char tempstr[6];
 
            itoa(windup_guard, tempstr);
 
            ssd1306_DrawString("G=", 1, 45);
 
            ssd1306_DrawString("    ", 1, 57);
 
@@ -550,53 +639,85 @@ void machine()
 
            }
 
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 
 
        case STATE_SETBOOTTOBREW:
 
        {
 
            // Write text to OLED
 
            // [ therm :: set windup ]
 
            // [ g = 12         ]
 
            ssd1306_DrawString("Boot to Brew", 0, 40);
 
            ssd1306_DrawString("Start on Boot", 0, 40);
 
            ssd1306_drawlogo();
 
 
            ssd1306_DrawString("btb=", 1, 45);
 
            ssd1306_DrawString("sob=", 1, 45);
 
            
 
            if(boottobrew)
 
                ssd1306_DrawString("Enabled ", 1, 70);
 
            else
 
                ssd1306_DrawString("Disabled", 1, 70);
 
 
            ssd1306_DrawString("Press to accept", 3, 40);
 
 
            // Button handler
 
            if(SW_BTN_PRESSED) {
 
                save_settings();
 
                state = STATE_IDLE;
 
                state = STATE_SETUNITS;
 
            }
 
            else if(!GPIO_ReadInputDataBit(SW_UP)) {
 
                boottobrew = 1;
 
            }
 
            else if(!GPIO_ReadInputDataBit(SW_DOWN)) {
 
                boottobrew = 0;
 
            }
 
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 
 
        case STATE_SETUNITS:
 
        {
 
            // Write text to OLED
 
            // [ therm :: set windup ]
 
            // [ g = 12         ]
 
            ssd1306_DrawString("Units: ", 0, 40);
 
            ssd1306_drawlogo();
 
 
            if(temp_units == TEMP_UNITS_FAHRENHEIT)
 
                ssd1306_DrawString("Fahrenheit", 1, 60);
 
            else
 
                ssd1306_DrawString("Celsius   ", 1, 60);
 
 
            ssd1306_DrawString("Press to accept", 3, 40);
 
 
            // Button handler
 
            if(SW_BTN_PRESSED) {
 
                save_settings();
 
                state = STATE_IDLE;
 
            }
 
            else if(!GPIO_ReadInputDataBit(SW_UP)) {
 
                temp_units = TEMP_UNITS_FAHRENHEIT;
 
            }
 
            else if(!GPIO_ReadInputDataBit(SW_DOWN)) {
 
                temp_units = TEMP_UNITS_CELSIUS;
 
            }
 
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 
 
 
        case STATE_PREHEAT_BREW:
 
        {
 
            // Write text to OLED
 
            // [ therm : preheating brew ]
 
            // [ 30 => 120 C             ]
 
            ssd1306_DrawString("Preheating...", 0, 0);
 
            //ssd1306_drawlogo();
 
            draw_setpoint();
 
            pid_enabled = 1;
 
	    setpoint = setpoint_brew;
 
 
            // Button handler
 
@@ -683,24 +804,47 @@ void machine()
 
                state = STATE_IDLE;
 
		save_setpoints(); // TODO: Check for mod
 
            }
 
            else {
 
                user_input(&setpoint_steam);
 
            }
 
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 
 
        case STATE_TC_ERROR:
 
        {
 
            // Write text to OLED
 
            // [ therm : ready to steam ]
 
            // [ 30 => 120 C            ]
 
            ssd1306_DrawString("Error:", 0, 0);
 
            ssd1306_DrawString("Connect thermocouple", 1, 0);
 
            ssd1306_DrawString("Press -> to ignore", 3, 0);
 
 
            // Button handler
 
            if(SW_BTN_PRESSED) {
 
                state = STATE_IDLE;
 
            }
 
            else if(SW_RIGHT_PRESSED) {
 
                ignore_tc_error = 1;
 
                state = STATE_IDLE;
 
            }
 
            // Event Handler
 
            // Maybe handle if TC is plugged in
 
            // N/A
 
 
 
        } break;
 
 
        // Something is terribly wrong
 
        default:
 
        {
 
            state = STATE_IDLE;
 
            pid_enabled = 0;
 
 
        } break;
 
            
 
    }
 
 
    if(last_state != state) {
 
        // Clear screen on state change
0 comments (0 inline, 0 general)