Changeset - 5a612d89cbaf
[Not reviewed]
default
0 1 1
Ethan Zonca - 10 years ago 2014-08-24 00:21:36
ez@ethanzonca.com
Added config.h
2 files changed with 20 insertions and 13 deletions:
main.c
1
13
0 comments (0 inline, 0 general)
config.h
Show inline comments
 
new file 100644
 
#ifndef CONFIG_H
 
#define CONFIG_H
 

	
 

	
 
#define SSR_PERIOD 200
 

	
 
#define LED_POWER GPIOB,GPIO_Pin_9
 
#define LED_STAT  GPIOA,GPIO_Pin_15
 

	
 
#define MAX_CS GPIOB,GPIO_Pin_12
 

	
 
#define SW_BTN  GPIOB, GPIO_Pin_3
 
#define SW_UP   GPIOB, GPIO_Pin_4
 
#define SW_DOWN GPIOB, GPIO_Pin_6
 
#define SW_LEFT GPIOB, GPIO_Pin_5
 
#define SW_RIGHT GPIOB, GPIO_Pin_7
 

	
 

	
 
#endif
main.c
Show inline comments
 
#include "main.h"
 
#include "stm32l100c_discovery.h"
 
#include "ssd1306.h"
 
#include "config.h"
 
 
// USB includes
 
#include "hw_config.h"
 
#include "usb_lib.h"
 
#include "usb_desc.h"
 
#include "usb_pwr.h"
 
#include "stringhelpers.h"
 
 
#define SSR_PERIOD 200
 
 
#define LED_POWER GPIOB,GPIO_Pin_9
 
#define LED_STAT  GPIOA,GPIO_Pin_15
 
 
#define MAX_CS GPIOB,GPIO_Pin_12
 
 
// TODO: Grab buttonpresses with interrupts
 
// TODO: Eliminate screen buffer since we aren't using it...
 
#define SW_BTN  GPIOB, GPIO_Pin_3
 
#define SW_UP   GPIOB, GPIO_Pin_4
 
#define SW_DOWN GPIOB, GPIO_Pin_6
 
#define SW_LEFT GPIOB, GPIO_Pin_5
 
#define SW_RIGHT GPIOB, GPIO_Pin_7
 
 
// 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;
 
 
// State definition
 
enum state {
 
    STATE_IDLE = 0,
 
 
    STATE_SETP,
 
    STATE_SETI,
 
    STATE_SETD,
 
 
    STATE_PREHEAT_BREW,
 
    STATE_MAINTAIN_BREW,
 
    STATE_PREHEAT_STEAM,
 
    STATE_MAINTAIN_STEAM,
 
};
 
 
 
 
static __IO uint32_t TimingDelay;
 
 
// Move to header file
 
void init_gpio();
 
void init_spi();
 
void process();
 
void machine();
 
 
int main(void)
 
{
 
 
    // Init clocks
 
    SystemInit();
 
 
    // Init GPIO
 
    init_gpio();
 
 
    // Init USB
 
    //Set_USBClock();
 
    //USB_Interrupts_Config();
 
    //USB_Init();
 
 
    // Turn on power LED
 
    GPIO_SetBits(LED_POWER);
 
 
    // TODO: Awesome pwm of power LED (TIM4_CH4 or TIM11_CH1)
 
    // TODO: PWM of stat led (TIM3_CH2)
 
 
    // Configure 1ms SysTick (change if more temporal resolution needed) 
 
    RCC_ClocksTypeDef RCC_Clocks;
 
    RCC_GetClocksFreq(&RCC_Clocks);
 
    SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000);
 
 
    // Init SPI busses
 
    init_spi();
 
 
    // Init OLED over SPI
 
    ssd1306_Init();
 
    ssd1306_block_write();
 
 
    // Startup screen 
 
    ssd1306_DrawString("therm v0.1", 1, 40);
 
    ssd1306_DrawString("protofusion.org/therm", 3, 0);
 
    Delay(1500);
 
    ssd1306_block_write();
 
 
    // Main loop
 
    while(1)
 
    {
 
        // Process sensor inputs
 
        process();
 
 
        // Run state machine
 
        machine(); 
 
    }
 
}
 
 
 
 
// Read temperature and update global temp vars
 
int16_t temp = 0;
 
uint8_t temp_frac = 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);
 
    }
 
    else if(temp_pre & 0b0000000000000001) {
 
        ssd1306_DrawString("Error: No TC", 2, 40);
 
        temp = 0;
 
        temp_frac = 0;
 
    }
 
    else 
 
    {
 
        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;
 
        }
 
    }
 
 
    // Deassert CS
 
    Delay(1);
 
    GPIO_SetBits(MAX_CS);
 
}
 
 
uint32_t ticks = 0;
 
uint32_t last_ssr_on = 0;
 
uint32_t last_led = 0;
 
int32_t setpoint = 0;
 
uint16_t k_p = 1;
 
uint16_t k_i = 1;
 
uint16_t k_d = 1;
 
uint8_t ssr_output = 0; // Duty cycle of ssr, 0 to SSR_PERIOD 
 
 
// Process things
 
void process()
 
{
 
    update_temp(); // Read MAX31855
 
 
    // TODO: Add calibration offset (linear)
 
 
    if(ticks - last_led > 400) 
 
    {
 
        GPIO_ToggleBits(LED_POWER);
 
        last_led = ticks;
 
    }
 
 
    // Every 200ms, set the SSR on
 
    if(ticks - last_ssr_on > SSR_PERIOD)
 
    {
 
        GPIO_SetBits(LED_STAT);
 
        last_ssr_on = ticks;
 
    }
 
    
 
    // Kill SSR after elapsed period less than SSR_PERIOD 
 
    if(ticks - last_ssr_on > ssr_output || !ssr_output)
 
    {
 
        GPIO_ResetBits(LED_STAT);
 
    }
 
}
 
 
void draw_setpoint() {
 
    char tempstr[3];
 
    itoa_fp(temp, temp_frac, tempstr);
 
    //ssd1306_DrawString("        ", 3, 40);
 
    ssd1306_DrawString(tempstr, 3, 40);
 
    ssd1306_DrawString("-> ", 3, 80);
 
    itoa(setpoint, tempstr);
 
    ssd1306_DrawString("    ", 3, 95);
 
    ssd1306_DrawString(tempstr, 3, 95);
 
}
 
 
 
 
 
 
uint8_t state = STATE_IDLE;
 
uint8_t goto_mode = 2;
 
 
// State machine
 
void machine()
 
{
 
    uint8_t last_state = state;
 
 
    switch(state)
 
    {
 
        // Idle state
 
        case STATE_IDLE:
 
        {
 
            // Write text to OLED
 
            // [ therm :: idle ]
 
            ssd1306_DrawString("therm :: idle ", 0, 40);
 
 
            char tempstr[6];
 
            itoa_fp(temp, temp_frac, tempstr);
 
            ssd1306_DrawString("Temp: ", 3, 40);
 
            ssd1306_DrawString("    ", 3, 70);
 
            ssd1306_DrawString(tempstr, 3, 72);
 
 
            ssd1306_drawlogo();
 
 
            switch(goto_mode) {
 
                case 2:
 
                {
 
                    ssd1306_DrawString("-> brew     ", 1, 40);
 
                } break;
 
 
                case 1:
 
                {
 
                    ssd1306_DrawString("-> set P/I/D", 1, 40);
 
                } break;
 
 
                case 0:
 
                {
 
                    ssd1306_DrawString("-> setup    ", 1, 40);
 
                } break;
 
            }
 
 
            // Button handler
 
            if(!GPIO_ReadInputDataBit(SW_BTN)) {
 
                switch(goto_mode) {
 
                    case 2:
 
                        state = STATE_PREHEAT_BREW;
 
                        break;
 
                    case 1:
 
                        state = STATE_SETP;
 
                        break;
 
                    case 0:
 
                        state = STATE_SETP;
 
                        break;
 
                    default:
 
                        state = STATE_PREHEAT_BREW;
 
                }
 
            }
 
            else if(!GPIO_ReadInputDataBit(SW_UP) && goto_mode < 2) {
 
                goto_mode++;
 
            }
 
            else if(!GPIO_ReadInputDataBit(SW_DOWN) && k_p > 0 && goto_mode > 0) {
 
                goto_mode--;
 
            }
 
 
 
            // Event Handler
 
            // N/A
 
 
        } break;
 
 
        case STATE_SETP:
 
        {
 
            // Write text to OLED
 
            // [ therm :: set p ]
 
            // [ p = 12         ]
 
            ssd1306_DrawString("Proportional", 0, 40);
 
 
            char tempstr[6];
 
            itoa(k_p, tempstr);
 
            ssd1306_DrawString("P=", 1, 45);
 
            ssd1306_DrawString("    ", 1, 57);
 
            ssd1306_DrawString(tempstr, 1, 57);
 
 
            ssd1306_DrawString("Press to accept", 3, 40);
 
            
 
            // Button handler
 
            if(!GPIO_ReadInputDataBit(SW_BTN)) {
 
                state = STATE_SETI;
 
            }
 
            else if(!GPIO_ReadInputDataBit(SW_UP)) {
 
                k_p++;
 
            }
 
            else if(!GPIO_ReadInputDataBit(SW_DOWN) && k_p > 0) {
 
                k_p--;
 
            }
 
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 
 
        case STATE_SETI:
 
        {
 
            // Write text to OLED
 
            // [ therm :: set i ]
 
            // [ i = 12         ]
 
            ssd1306_DrawString("Integral", 0, 40);
 
 
            char tempstr[6];
 
            itoa(k_i, tempstr);
 
            ssd1306_DrawString("I=", 1, 45);
 
            ssd1306_DrawString("    ", 1, 57);
 
            ssd1306_DrawString(tempstr, 1, 57);
 
 
            ssd1306_DrawString("Press to accept", 3, 40);
 
            
 
            // Button handler
 
            if(!GPIO_ReadInputDataBit(SW_BTN)) {
 
                state = STATE_SETD;
 
            }
 
            else if(!GPIO_ReadInputDataBit(SW_UP)) {
 
                k_i++;
 
            }
 
            else if(!GPIO_ReadInputDataBit(SW_DOWN) && k_i > 0) {
 
                k_i--;
 
            }
 
 
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 
 
        case STATE_SETD:
 
        {
 
            // Write text to OLED
 
            // [ therm :: set d ]
 
            // [ d = 12         ]
 
            ssd1306_DrawString("Derivative", 0, 40);
 
 
            char tempstr[6];
 
            itoa(k_d, tempstr);
 
            ssd1306_DrawString("D=", 1, 45);
 
            ssd1306_DrawString("    ", 1, 57);
 
            ssd1306_DrawString(tempstr, 1, 57);
 
 
            ssd1306_DrawString("Press to accept", 3, 40);
 
 
            // Button handler
 
            if(!GPIO_ReadInputDataBit(SW_BTN)) {
 
                state = STATE_IDLE;
 
            }
 
            else if(!GPIO_ReadInputDataBit(SW_UP)) {
 
                k_d++;
 
            }
 
            else if(!GPIO_ReadInputDataBit(SW_DOWN) && k_d > 0) {
 
                k_d--;
 
            }
 
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 
 
        case STATE_PREHEAT_BREW:
 
        {
 
            // Write text to OLED
 
            // [ therm : preheating brew ]
 
            // [ 30 => 120 C             ]
 
            ssd1306_DrawString("Preheating...", 0, 40);
 
            draw_setpoint();
 
 
            // Button handler
 
            if(!GPIO_ReadInputDataBit(SW_BTN)) {
 
                state = STATE_IDLE;
 
            }
 
 
            // Event Handler
 
            if(temp >= setpoint) {
 
                state = STATE_MAINTAIN_BREW;
 
            }
 
 
 
        } break;
 
 
        case STATE_MAINTAIN_BREW:
 
        {
 
            // Write text to OLED
 
            // [ therm : ready to brew ]
 
            // [ 30 => 120 C           ]
 
            ssd1306_DrawString("Ready to Brew!", 0, 40);
 
            draw_setpoint();
 
 
            // Button handler
 
            if(!GPIO_ReadInputDataBit(SW_BTN)) {
 
                state = STATE_IDLE;
 
            }
 
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 
 
        case STATE_PREHEAT_STEAM:
 
        {
 
            // Write text to OLED
 
            // [ therm : preheating steam ]
 
            // [ 30 => 120 C           ]
 
            ssd1306_DrawString("Preheating...", 0, 40);
 
            draw_setpoint();
 
 
            // Button handler
 
            if(!GPIO_ReadInputDataBit(SW_BTN)) {
 
                state = STATE_IDLE;
 
            }
 
 
            // Event Handler
 
            if(temp >= setpoint) {
 
                state = STATE_MAINTAIN_STEAM;
 
            }
 
 
 
        } break;
 
 
        case STATE_MAINTAIN_STEAM:
 
        {
 
            // Write text to OLED
 
            // [ therm : ready to steam ]
 
            // [ 30 => 120 C            ]
 
            ssd1306_DrawString("Ready to Steam!", 0, 40);
 
            draw_setpoint();
 
 
            // Button handler
0 comments (0 inline, 0 general)