Changeset - 6cc8fa5ae0f6
[Not reviewed]
default
0 3 0
Ethan Zonca - 8 years ago 2017-07-25 13:17:30
ezonca@sealandaire.com
Temp reading finally working!
3 files changed with 15 insertions and 17 deletions:
0 comments (0 inline, 0 general)
lib/max31856/max31856.c
Show inline comments
 
//
 
// MAX31856: Driver to configure and read temperature from the MAX31856 thermoouple-to-Digital IC
 
//
 

	
 
#include "max31856.h"
 
#include "states.h"
 
#include "error.h"
 

	
 
// Private variables
 
static float temp_latest = 0.0;
 
static float temp_avg = 0.0;
 

	
 
SPI_HandleTypeDef* spiport;
 
static GPIO_TypeDef* csport;
 
static uint32_t cspin;
 

	
 

	
 
// Private prototypes
 
static void __cs_assert(void);
 
static void __cs_deassert(void);
 
static void __write_reg(uint8_t reg, uint8_t data);
 
static void __read_reg(uint8_t reg, uint8_t* rxbuf, uint8_t len);
 

	
 

	
 
// Initialize the MAX31856 driver
 
void max31856_init(SPI_HandleTypeDef* spi_port, GPIO_TypeDef* cs_port, uint32_t cs_pin, uint32_t sensor_type)
 
{
 
	// Set CS pin references
 
	csport = cs_port;
 
	cspin = cs_pin;
 

	
 
	// Set SPI port reference
 
	spiport = spi_port;
 

	
 
	// Configure the CS pin for output
 
	GPIO_InitTypeDef GPIO_InitStruct;
 
	GPIO_InitStruct.Pin = cs_pin;
 
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 
	GPIO_InitStruct.Pull = GPIO_NOPULL;
 
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 
	HAL_GPIO_Init(cs_port, &GPIO_InitStruct);
 

	
 
	// MAX31856
 
	// - set to continuous conversion mode
 
	// - probably no filtering, we'll do that on this side of things
 
	// - set up to read the typical open/short faults but not the high/low alarms
 

	
 

	
 
	// TODO: Enable open/short detection
 
	// Enables auto conv
 
	__write_reg(MAX31856_CR0_REG, MAX31856_CR0_AUTOCONVERT); //  MAX31856_CR0_OCFAULT0
 

	
 
	// Averaging set to 1 sample, TC type set to K
 
	__write_reg(MAX31856_CR1_REG, MAX31856_TCTYPE_K);
 

	
 
	// sensor type - could we just mask bits off? maybe optimize the enum for this
 
}
 

	
 

	
 
// Pull reading from the MAX31856 IC
 
float max31856_process(void)
 
{
 
	uint8_t tempbuf[3];
 
	__read_reg(MAX31856_LTCBH_REG, tempbuf, 3);
 

	
 

	
 
	int32_t temp24 = tempbuf[0] << 16 | tempbuf[1] << 8 | tempbuf[0];
 
	volatile int32_t temp24 = tempbuf[0] << 16 | tempbuf[1] << 8 | tempbuf[2];
 
	if (temp24 & 0x800000) {
 
		temp24 |= 0xFF000000;  // fix sign
 
	}
 

	
 
	temp24 >>= 5;  // bottom 5 bits are unused
 

	
 
	float tempfloat = temp24;
 
	tempfloat *= 0.0078125;
 

	
 
	temp_latest = tempfloat;
 
	return tempfloat;
 

	
 

	
 

	
 

	
 
	// Read temperature from the MAX31856 (approx 10hz optimally)
 
//	uint8_t data[] = {0,0,0,0};
 
//	HAL_SPI_Transmit(spiport, data, 1, 100);
 

	
 
}
 

	
 

	
 
// Return latest temperature reading (unaveraged, deg C)
 
float max31856_latest_temp(void)
 
{
 
	return temp_latest;
 
}
 

	
 

	
 
// Return average temperature reading (deg C)
 
float max31856_avg_temp(void)
 
{
 
	return temp_latest;
 
}
 

	
 

	
 
static void __write_reg(uint8_t reg, uint8_t data)
 
{
 
	// Set write bit
 
	reg |= MAX31856_WRITE_BIT;
 

	
 
	uint8_t outarr[2] = {reg, data};
 
	uint8_t dummyrx[2];
 

	
 
	// Assert the bus
 
	__cs_assert();
 

	
 
	HAL_Delay(1);
 

	
 
	// Write data
 
	volatile HAL_StatusTypeDef res = HAL_SPI_Transmit(spiport, outarr, 2, 100);
 
	volatile HAL_StatusTypeDef res = HAL_SPI_TransmitReceive(spiport, outarr, dummyrx, 2, 100);
 

	
 
	HAL_Delay(1);
 

	
 
	// Release the bus
 
	__cs_deassert();
 
}
 

	
 
static void __read_reg(uint8_t reg, uint8_t* rxbuf, uint8_t len)
 
{
 
	// Transmit buffer only uses first item for reg addr
 
	uint8_t regarr[1] = {reg};
 
	uint8_t regarr[1];
 
	regarr[0] = reg;
 

	
 
	HAL_Delay(1);
 
	uint8_t dummyrx[12] = {0};
 
	uint8_t dummytx[12] = {0};
 

	
 
	// Assert the bus
 
	__cs_assert();
 
	HAL_Delay(1);
 

	
 
	// Send address
 
	volatile HAL_StatusTypeDef res = HAL_SPI_Transmit(spiport, regarr, 1, 100);
 
	HAL_Delay(1);
 
	HAL_SPI_TransmitReceive(spiport, regarr, dummyrx, 1, 100);
 

	
 
	// Receive data
 
	volatile HAL_StatusTypeDef res2 = HAL_SPI_Receive(spiport, rxbuf, len, 100);
 
	HAL_Delay(1);
 
	HAL_SPI_TransmitReceive(spiport, dummytx, rxbuf, len, 100);
 

	
 
	// Release bus
 
	__cs_deassert();
 
	HAL_Delay(1);
 

	
 
}
 

	
 
static void __cs_assert(void)
 
{
 
	HAL_GPIO_WritePin(csport, cspin, 0);
 
}
 

	
 
static void __cs_deassert(void)
 
{
 
	HAL_GPIO_WritePin(csport, cspin, 1);
 
}
lib/ssd1306/ssd1306.c
Show inline comments
 
#include "stm32f3xx_hal.h"
 
#include "ssd1306.h"
 
 
 
SPI_HandleTypeDef hspi1;
 
 
 
// SPI handle accessor
 
SPI_HandleTypeDef* spi_get()
 
{
 
    return &hspi1;
 
}
 
 
 
// Write command to OLED
 
static void WriteCommand(unsigned char command)
 
{
 
  SSD_CS_Low();
 
  SSD_A0_Low();
 
  SPI_SendByte(command);
 
  SSD_CS_High();
 
}
 
 
// Write data to OLED
 
static void WriteData(unsigned char data)
 
{
 
  SSD_CS_Low();
 
  SSD_A0_High();
 
  SPI_SendByte(data);
 
  SSD_CS_High();
 
}
 
 
// Initialize OLED
 
void ssd1306_init(void)
 
{
 
	__SPI3_CLK_ENABLE();
 
	__GPIOA_CLK_ENABLE();
 
	__GPIOB_CLK_ENABLE();
 
	GPIO_InitTypeDef GPIO_InitStruct;
 
 
	/*Configure GPIO pins : OLED_CS_Pin OLED_RESET_Pin OLED_DC_Pin */
 
	GPIO_InitStruct.Pin = OLED_CS_Pin|OLED_RESET_Pin|OLED_DC_Pin;
 
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 
	GPIO_InitStruct.Pull = GPIO_NOPULL;
 
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 
	HAL_GPIO_Init(OLED_DC_GPIO_Port, &GPIO_InitStruct);
 
 
 
	// Set up MOSI/MISO/SCK
 
	GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
 
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 
	GPIO_InitStruct.Pull = GPIO_NOPULL;
 
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 
	GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
 
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
 
 
	// Set up SPI port for OLED
 
	hspi1.Instance = SPI3;
 
	hspi1.Init.Mode = SPI_MODE_MASTER;
 
	hspi1.Init.Direction = SPI_DIRECTION_2LINES;
 
	hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
 
	hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
 
	hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
 
	hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
 
	hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
 
	hspi1.Init.NSS = SPI_NSS_SOFT;
 
	hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; //16;
 
	hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
 
	hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
 
	hspi1.Init.TIMode = SPI_TIMODE_DISABLED;
 
	hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
 
	hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLED;
 
	HAL_SPI_Init(&hspi1);
 
 
 
	// Generate a reset
 
	SSD_Reset_Low();
 
	uint32_t i;
 
	for(i=5000; i>1; i--)
 
	SSD_Reset_High();
 
 
	WriteCommand(0xAE);
 
	WriteCommand(0xD5);
 
	WriteCommand(0x80);
 
	WriteCommand(0xA8);
 
	WriteCommand(0x1F);
 
	WriteCommand(0xD3);
 
	WriteCommand(0x00);
 
	WriteCommand(0x40 | 0x00); // line #0
 
	WriteCommand(0x8D);
 
	WriteCommand(0x14); //10 or 14 if not externalvcc
 
	WriteCommand(0x20);
 
	WriteCommand(0x00);
 
	//  WriteCommand(0xA0 | 0x1); // segremap (normal)
 
	WriteCommand(0xA0); // segremap (flip)
 
	//  WriteCommand(0xC8); // comscandec (normal)
 
	WriteCommand(0xC0); // comscandec (flip)
 
	WriteCommand(0xDA); // setcompins
 
	WriteCommand(0x02);
 
	WriteCommand(0x81); // contrast
 
	WriteCommand(0x0F); // contrast value. 8f is a good one.
 
	WriteCommand(0xD9);
 
	WriteCommand(0xF1); //22 or F1 if not externalvcc
 
	WriteCommand(0xDB);
 
	WriteCommand(0x40);
 
	WriteCommand(0xA4); // dispalyallon_resume
 
	WriteCommand(0xA6); // normaldisplay
 
 
 
	WriteCommand(0xAF); // display on
 
}
 
 
 
// Times New Roman font
 
static const char fontData[][5] =
 
{                                       // Refer to "Times New Roman" Font Database
 
                                        //   Basic Characters
 
    {0x00,0x00,0x00,0x00,0x00},         //   (  0)    - 0x0020 No-Break Space
 
    {0x00,0x00,0x4F,0x00,0x00},         //   (  1)  ! - 0x0021 Exclamation Mark
 
    {0x00,0x07,0x00,0x07,0x00},         //   (  2)  " - 0x0022 Quotation Mark
 
    {0x14,0x7F,0x14,0x7F,0x14},         //   (  3)  # - 0x0023 Number Sign
 
    {0x24,0x2A,0x7F,0x2A,0x12},         //   (  4)  $ - 0x0024 Dollar Sign
 
    {0x23,0x13,0x08,0x64,0x62},         //   (  5)  % - 0x0025 Percent Sign
 
    {0x36,0x49,0x55,0x22,0x50},         //   (  6)  & - 0x0026 Ampersand
 
    {0x00,0x05,0x03,0x00,0x00},         //   (  7)  ' - 0x0027 Apostrophe
 
    {0x00,0x1C,0x22,0x41,0x00},         //   (  8)  ( - 0x0028 Left Parenthesis
 
    {0x00,0x41,0x22,0x1C,0x00},         //   (  9)  ) - 0x0029 Right Parenthesis
 
    {0x14,0x08,0x3E,0x08,0x14},         //   ( 10)  * - 0x002A Asterisk
 
    {0x08,0x08,0x3E,0x08,0x08},         //   ( 11)  + - 0x002B Plus Sign
 
    {0x00,0x50,0x30,0x00,0x00},         //   ( 12)  , - 0x002C Comma
 
    {0x08,0x08,0x08,0x08,0x08},         //   ( 13)  - - 0x002D Hyphen-Minus
 
    {0x00,0x60,0x60,0x00,0x00},         //   ( 14)  . - 0x002E Full Stop
 
    {0x20,0x10,0x08,0x04,0x02},         //   ( 15)  / - 0x002F Solidus
 
    {0x3E,0x51,0x49,0x45,0x3E},         //   ( 16)  0 - 0x0030 Digit Zero
 
    {0x00,0x42,0x7F,0x40,0x00},         //   ( 17)  1 - 0x0031 Digit One
 
    {0x42,0x61,0x51,0x49,0x46},         //   ( 18)  2 - 0x0032 Digit Two
 
    {0x21,0x41,0x45,0x4B,0x31},         //   ( 19)  3 - 0x0033 Digit Three
 
    {0x18,0x14,0x12,0x7F,0x10},         //   ( 20)  4 - 0x0034 Digit Four
 
    {0x27,0x45,0x45,0x45,0x39},         //   ( 21)  5 - 0x0035 Digit Five
 
    {0x3C,0x4A,0x49,0x49,0x30},         //   ( 22)  6 - 0x0036 Digit Six
 
    {0x01,0x71,0x09,0x05,0x03},         //   ( 23)  7 - 0x0037 Digit Seven
 
    {0x36,0x49,0x49,0x49,0x36},         //   ( 24)  8 - 0x0038 Digit Eight
 
    {0x06,0x49,0x49,0x29,0x1E},         //   ( 25)  9 - 0x0039 Dight Nine
 
    {0x00,0x36,0x36,0x00,0x00},         //   ( 26)  : - 0x003A Colon
 
    {0x00,0x56,0x36,0x00,0x00},         //   ( 27)  ; - 0x003B Semicolon
 
    {0x08,0x14,0x22,0x41,0x00},         //   ( 28)  < - 0x003C Less-Than Sign
 
    {0x14,0x14,0x14,0x14,0x14},         //   ( 29)  = - 0x003D Equals Sign
 
    {0x00,0x41,0x22,0x14,0x08},         //   ( 30)  > - 0x003E Greater-Than Sign
 
    {0x02,0x01,0x51,0x09,0x06},         //   ( 31)  ? - 0x003F Question Mark
 
    {0x32,0x49,0x79,0x41,0x3E},         //   ( 32)  @ - 0x0040 Commercial At
 
    {0x7E,0x11,0x11,0x11,0x7E},         //   ( 33)  A - 0x0041 Latin Capital Letter A
 
    {0x7F,0x49,0x49,0x49,0x36},         //   ( 34)  B - 0x0042 Latin Capital Letter B
 
    {0x3E,0x41,0x41,0x41,0x22},         //   ( 35)  C - 0x0043 Latin Capital Letter C
 
    {0x7F,0x41,0x41,0x22,0x1C},         //   ( 36)  D - 0x0044 Latin Capital Letter D
 
    {0x7F,0x49,0x49,0x49,0x41},         //   ( 37)  E - 0x0045 Latin Capital Letter E
 
    {0x7F,0x09,0x09,0x09,0x01},         //   ( 38)  F - 0x0046 Latin Capital Letter F
 
    {0x3E,0x41,0x49,0x49,0x7A},         //   ( 39)  G - 0x0047 Latin Capital Letter G
 
    {0x7F,0x08,0x08,0x08,0x7F},         //   ( 40)  H - 0x0048 Latin Capital Letter H
 
    {0x00,0x41,0x7F,0x41,0x00},         //   ( 41)  I - 0x0049 Latin Capital Letter I
 
    {0x20,0x40,0x41,0x3F,0x01},         //   ( 42)  J - 0x004A Latin Capital Letter J
 
    {0x7F,0x08,0x14,0x22,0x41},         //   ( 43)  K - 0x004B Latin Capital Letter K
 
    {0x7F,0x40,0x40,0x40,0x40},         //   ( 44)  L - 0x004C Latin Capital Letter L
 
    {0x7F,0x02,0x0C,0x02,0x7F},         //   ( 45)  M - 0x004D Latin Capital Letter M
 
    {0x7F,0x04,0x08,0x10,0x7F},         //   ( 46)  N - 0x004E Latin Capital Letter N
src/display.c
Show inline comments
 
//
 
// Display: render menus on OLED display
 
//
 

	
 
#include "display.h"
 
#include "gpio.h"
 
#include "ssd1306/ssd1306.h"
 
#include "system/stringhelpers.h"
 
#include "flash.h"
 

	
 
// Private function prototypes
 
static void draw_setpoint(therm_status_t* status);
 

	
 

	
 
// Button transition variables
 
static uint8_t sw_btn_last = 0;
 
static uint8_t sw_up_last = 0;
 
static uint8_t sw_down_last = 0;
 
static uint8_t sw_left_last = 0;
 
static uint8_t sw_right_last = 0;
 

	
 

	
 
// Buttonpress macros
 
#define SW_BTN_PRESSED (sw_btn_last == 0 && sw_btn == 1) // rising edge on buttonpress
 
#define SW_UP_PRESSED (sw_up_last == 0 && sw_up == 1)
 
#define SW_DOWN_PRESSED (sw_down_last == 0 && sw_down == 1)
 
#define SW_LEFT_PRESSED (sw_left_last == 0 && sw_left == 1)
 
#define SW_RIGHT_PRESSED (sw_right_last == 0 && sw_right == 1)
 

	
 

	
 
// States
 
static uint8_t trigger_drawsetpoint = 1;
 
static int16_t last_temp = 21245;
 
static int16_t last_temp_frac = 21245;
 
static int16_t last_state = 123;
 
static uint8_t goto_mode = MODE_HEAT;
 
static uint8_t reset_mode = RESET_REBOOT;
 

	
 
static char* sensor_lookup[] = {"NTC", "K  ", "E  ", "N  ", "R  ", "S  ", "T  "};
 

	
 
static uint8_t toggle = 0;
 

	
 
void display_1hz(void)
 
{
 
	toggle = !toggle;
 
}
 

	
 
static char updown(void)
 
{
 
	if(toggle)
 
		return '\x8f';
 
	else
 
		return '\x90';
 
}
 

	
 
// Display state machine
 
void display_process(void)
 
{
 
	therm_status_t* status = runtime_status();
 
	therm_settings_t* set = flash_getsettings();
 

	
 

	
 
    uint8_t state_changed = status->state != last_state;
 
    last_state = status->state;
 
    
 
    uint8_t temp_changed = status->temp != last_temp;
 
    last_temp = status->temp;
 

	
 
    uint8_t sw_btn = !HAL_GPIO_ReadPin(SW_BTN);
 
    uint8_t sw_up = !HAL_GPIO_ReadPin(SW_UP);
 
    uint8_t sw_down = !HAL_GPIO_ReadPin(SW_DOWN);
 
    uint8_t sw_left = !HAL_GPIO_ReadPin(SW_LEFT);
 
    uint8_t sw_right = !HAL_GPIO_ReadPin(SW_RIGHT);
 

	
 
    switch(status->state)
 
    {
 
        // Idle state
 
        case STATE_IDLE:
 
        {
 
            // Write text to OLED
 
            // [ therm :: idle ]
 
            ssd1306_drawstring("therm \x87 idle ", 0, 40);
 
            status->pid_enabled = 0;
 

	
 
            if(temp_changed || state_changed) {
 
                char tempstr[16];
 
                snprintf(tempstr, 16, "Temp: %g", status->temp);
 
                ssd1306_drawstring("             ", 3, 40);
 
                snprintf(tempstr, 16, "Temp: %6.1f", status->temp);
 
//                ssd1306_drawstring("             ", 3, 40);
 

	
 
                ssd1306_drawstring(tempstr, 3, 40);
 
            }
 

	
 
            if (state_changed) {
 
            	ssd1306_drawlogo();
 
            }
 

	
 
            switch(goto_mode) {
 

	
 
                case MODE_HEAT:
 
                {
 
					if(set->val.plant_type == PLANT_HEATER)
 
						ssd1306_drawstring("\x83 heat      ", 1, 40);
 
					else
 
						ssd1306_drawstring("\x83 cool      ", 1, 40);
 

	
 
                } break;
 

	
 
                case MODE_SETUP:
 
                {
 
                    ssd1306_drawstring("\x83 setup    ", 1, 40);
 
                } break;
 

	
 
                case MODE_RESET:
 
                {
 
                    ssd1306_drawstring("\x83 reset    ", 1, 40);
 
                } break;
 

	
 
				#ifdef BOOTLOADER_SHORTCUT
 
                case MODE_BOOTLOADER:
 
                {
 
                    ssd1306_drawstring("\x83 dfu      ", 1, 40);
 
                }
 
				#endif
 
            }
 

	
 
            // Button handler
 
            if(SW_BTN_PRESSED) {
 
                switch(goto_mode) {
 
                    case MODE_HEAT:
 
                        status->state = STATE_PREHEAT;
 
                        break;
 
                    case MODE_SETUP:
 
                        status->state = STATE_SETSENSORTYPE;
 
                        break;
 
                    case MODE_RESET:
 
                        status->state = STATE_RESET;
 
                        reset_mode = RESET_REBOOT;
 
                        break;
 
					#ifdef BOOTLOADER_SHORTCUT
 
                    case MODE_BOOTLOADER:
 
                        ssd1306_clearscreen();
 
                        ssd1306_drawstring("Bootloader Entered", 0, 0);
 
                        ssd1306_drawstring("Device won't boot", 2, 0);
 
                        ssd1306_drawstring("until reflashed!", 3, 0);
 
//                        bootloader_enter(); // Resets into bootloader
 
                        status->state = STATE_RESET; // Just in case
 
                        break;
 
					#endif
 
                    default:
 
                        status->state = STATE_PREHEAT;
 
                }
 
            }
 
            else if(SW_DOWN_PRESSED && goto_mode < (MODE_SIZE - 1)) {
 
                goto_mode++;
 
            }
 
            else if(SW_UP_PRESSED && goto_mode > 0) {
 
                goto_mode--;
 
            }
 

	
 

	
 
            // Event Handler
 
            // N/A
 

	
 
        } break;
 

	
 

	
 

	
 
        case STATE_SETSENSORTYPE:
 
        {
 
            // Write text to OLED
 
            // [ therm :: set mode ]
 
            // [ m =          ]
 
            ssd1306_drawstring("Sensor Type", 0, 40);
 
            ssd1306_drawlogo();
 

	
 
            ssd1306_drawchar(updown(), 1, 52);
 
			ssd1306_drawstring(sensor_lookup[set->val.sensor_type], 1, 60);
 
            ssd1306_drawstring("Press to accept", 3, 40);
 

	
 
            // Button handler
 
            if(SW_BTN_PRESSED) {
 
                status->state = STATE_SETMODE;
 
            }
 
            else
0 comments (0 inline, 0 general)