STEAM GENERATOR using PIC16F873

Introduction

This program is a steam generator controller that is intended for use in a residential steam shower. It controls water inlet and drain valves, power to the heating element, and various level and thermal sensors.

Features

Push button automated control of the steam shower. High and low steam rates, extendable cycles, error conditions are sensed and handled.

steam_controler_backside

Specifications

  • Power: 220VAC, 3000W
  • Time to boil: 6 minutes
  • Added time to preheat steam room: 10 minutes
  • Steam cycle: 20 minutes, plus additional 20 minute cycles if requested
  • Steam level: Full steam, low steam
  • Time to cool and drain: 20 minutes, typical
  • Error conditions: six

Construction

This project works quite well but has not passed the prototype stage yet. (It’s still built on a wooden platform!)

The tank is a 4″ copper pipe with end caps. It is silver soldered to withstand heat. The replacable 3000W heating element extends inward through one end of the tank. Stainless bolts are used. The relay card is a pre-existing unit that I had in my collection. The 220/24V transformer, solid state relay, cooling fan are below the relay card. The “U” shaped 1/4″ flexible copper tubing alongside the tank is for preheating the incoming water so that it doesn’t squelch the steam when the inlet water valve opens.

STEAM GENERATOR schematic

Code:

/****************************************************************
STEAMGEN07.C

This is a steam generator.

WORKING CODE

ERRORS - count the number of quick flashes
    1 - not drained at beginning
    2 - not filled within time limit during initial fill cycle
    3 - not filled within time limit during rinse cycle
    4 - not filled to limit during heating within time limit
    5 - over temperature during preheat or soak cycles
    6 - under temperature after preheat cycle

LED FLASH
    SLOW - filling, preheating, draining
    SOLID - soak mode
    FAST - stop and wait (warn) period

                   ---------
           +5--20-|Vdd    C0|-11--- Heat-A relay
                  |       C1|-12--- Heat-B relay
          Gnd--08-|Vss    C2|-13--- Heat - SSR
          Gnd--19-|Vss    C3|-14--- Fill
         4MHz--10-|Xtal   C4|-15--- Drain
             --09-|Xtal     |
                  |         | PROGRAMMING CONNECTOR
                  |       B7|-28--DATA
                  |       B6|-27--CLK
                  |     MCLR|-01--MCLR
                  |         |     GND
                  | 16F876  |
                  |         |
       Level --21-|B0     C5|-16-- LED1
         Sw1 --22-|B1     C6|-17-- LED2
         Sw2 --23-|B2     B4|-25-- LED RETURNS
      DS1820 --03-|A1     B3|-24-- BEEPER
                  |       B5|-26-- COOLING FAN
                   ---------

**********************************************************/

#include < 16F876.H >
#include < jonsinc.h >
#fuses XT, NOPROTECT, PUT, NOWDT, BROWNOUT, NOLVP, NOCPD, NOWRT

#define RELAY_HEAT_A         PIN_C0
#define RELAY_HEAT_B         PIN_C1
#define RELAY_SSR            PIN_C2
#define RELAY_FILL           PIN_C3
#define RELAY_DRAIN          PIN_C4
#define LED_1                PIN_C5
#define LED_2                PIN_C6
#define SWITCH_LEVEL         PIN_B0
#define SWITCH_1             PIN_B1
#define SWITCH_2             PIN_B2
#define BEEPER               PIN_B3
#define LED_RETURN           PIN_B4
#define DS1820_DATA_PIN      PIN_A1
#define FAN                  PIN_B5
//============================
#define PERCENT_100          4
#define PERCENT_75           3
#define PERCENT_50           2
#define PERCENT_25           1
#define PERCENT_0            0
#define LED_FLASH_NONE       0
#define LED_FLASH_SLOW       1
#define LED_FLASH_FAST       2
#define LED_INIT_FLASH_COUNT 16
#define MINIMUM_INTERVAL     1
#define HIGH_STEAM           1
#define LOW_STEAM            2
//============================
#define STATE_START          0
#define STATE_INITIAL_CHECKS 1
#define STATE_READ_SWITCHES  2
#define STATE_FILL           3
#define STATE_PREHEAT        4
#define STATE_SOAK           5
#define STATE_WARN           6
#define STATE_DRAIN          7
#define STATE_ERROR          9
//============================
#define ERROR_NONE                    0
#define ERROR_NOT_DRAINED             1
#define ERROR_NOT_FILLED_DURING_FILL  2
#define ERROR_NOT_FILLED_DURING_RINSE 3
#define ERROR_FILL_ABSENCE            4
#define ERROR_OVERTEMP                5
#define ERROR_UNDERTEMP               6
//============================
// times in seconds
#define TIME_FILL_LIMIT      240
#define TIME_DRAIN           160
#define TIME_PREBOIL         360
#define TIME_PREHEAT_SHOWER  600
#define TIME_SOAK_MODE       1200
#define TIME_STOP_AND_WAIT   130
#define TIME_FILL_ABSENCE    300
#define TIME_TEMPERATURE_MEAS 10
// times in mS
#define TIME_ADD_WATER_INCR  1000
#define TIME_ADD_WATER_DELAY 100
#define TIME_DRAIN_COOL_FILL 10000
#define TIME_INITIAL_OVERFILL 3000
// times in uS
#define BEEPER_PERIOD_DELAY  518
// number of cycles for beeper
#define BEEP_CYCLES           500
//============================
// DS1820 temperature sensor
#define DS1820_SKIP_ROM          0xCC
#define DS1820_READ_SCRATCHPAD   0xBE
#define DS1820_CONVERT_T         0x44
// temperature in degrees C
#define TEMPERATURE_DRAIN_LIMIT  65
#define TEMPERATURE_OVER         105
#define TEMPERATURE_UNDER        90
//============================

#use delay ( clock=6000000 )
#use standard_io ( A )
#use standard_io ( B )
#use standard_io ( C )

void CheckSwitches ( void );
void AddWaterIfNecessary ( void );
void FlashErrorCode ( cError );
void AllRelaysOff ( void );
void Beep ( char cCount );
void SetHeaterPower ( char cLevel );
char ReadTemperature ( void );
void ResetDS1820 ( void );
void WriteDS1820 ( void );
void ReadDS1820 ( void );
void WaitForConversion ( void );

static char cInterruptCount;
static long iSecondCount, iFillOvertimeCount;
static char cSwitch1Count, cSwitch1on;
static char cSwitch2Count, cSwitch2on;
static char cError, cState, cMode, cOff, cResetCount;
static char cLedFlash, cLedOn, cSSRon, cSSRcount, cDebugMode;
static char cPower, cDutyCycleCount, cDutyCycleState;
static char cShiftBit,cDataOut, cTemperatureSecondCount;
static long iDataIn;

//*************************************************************************

#int_rtcc
void TimerInterrupt ( void )      // 21.760mS tick, 46 interrupts per second
    {
    // ONE-SECOND TICK
    if ( cInterruptCount++ == 47 )      // a little more than one second so flashes divide evenly
        {
        cInterruptCount = 0;            // restart interrupt count
        iSecondCount++;                 // increment second count
        cTemperatureSecondCount++;      // increment temperature second count
        iFillOvertimeCount++;           // increment overtime count
        }
    // SOLID STATE RELAY POWER CYCLING
    if ( cDutyCycleCount++ >= 4 )      // is it 84mS yet? (sets the overall duty cycle granularity)
        {
        cDutyCycleCount = 0;            // reset
        if ( cDutyCycleState == cPower )     // is heat cycle done yet?
            {
            output_low ( RELAY_SSR );  // turn solid state relay off
            }
        else
            {
            if ( cDutyCycleState == 0 )     // if first state
                {
                output_high ( RELAY_SSR );  // turn solid state relay on
                }
            }
        if ( cDutyCycleState++ >= 3 )   // increment state
            {
            cDutyCycleState = 0;        // reset
            }
        }
    // LED FLASH/SOLID CONTROL
    switch ( cLedFlash )
        {
        case LED_FLASH_NONE:
            {
            cLedOn = YES;
            break;
            }
        case LED_FLASH_SLOW:
            {
            if ( ( cInterruptCount % 24 ) == 0 )
                {
                cLedOn ^= 1;
                }
            break;
            }
        case LED_FLASH_FAST:
            {
            if ( ( cInterruptCount % 8 ) == 0 )
                {
                cLedOn ^= 1;
                }
            break;
            }
        }
    if ( cLedOn == YES )
        {
        output_low ( LED_RETURN );     // LED on
        }
    else
        {
        output_high ( LED_RETURN );    // LED off
        }
    // SWITCH 1 SENSE
    if ( input ( SWITCH_1 ) == LOW )    // if pressed
        {
        if ( cSwitch1Count++ >= 92 )     // increment count
            {
            cSwitch1Count = 92;          // prevent wrap, limit to highest needed
            }
        }
    else                                // when button is released
        {
        if ( cSwitch1Count >= 92 )       // if was pressed for two seconds
            {
            cOff = YES;                 // signal OFF
            }
        else
            {
            if ( cSwitch1Count >= 2 )    // else if was pressed momentarily
                {
                cSwitch1on = YES;       // signal normal press
                }
            }
        cSwitch1Count = 0;              // switch up, restart
        }
    // SWITCH 2 SENSE
    if ( input ( SWITCH_2 ) == LOW )    // if pressed
        {
        if ( cSwitch2Count++ >= 92 )     // increment count
            {
            cSwitch2Count = 92;          // prevent wrap, limit to highest needed
            }
        }
    else                                // when button is released
        {
        if ( cSwitch2Count >= 92 )       // if was pressed for two seconds
            {
            cOff = YES;                 // signal OFF
            }
        else
            {
            if ( cSwitch2Count >= 2 )    // else if was pressed momentarily
                {
                cSwitch2on = YES;       // signal normal press
                }
            }
        cSwitch2Count = 0;              // switch up, restart
        }
    // RESET (PRESS BOTH SWITCHES SIMULTANEOUSLY)
    if ( ( input ( SWITCH_1 ) == LOW ) && ( input ( SWITCH_2 ) == LOW ) )    // if pressed for three seconds
        {
        if ( cResetCount++ >= 143 )     // increment count
            {
            cResetCount = 143;          // cap it
            }
        }
    else                                // when button is released
        {
        if ( cResetCount >= 143 )       // if was pressed for five seconds
            {
            reset_cpu();
            }
        cResetCount = 0;              // switch up, restart
        }
    }

//****************************************************************************

For more detail: STEAM GENERATOR using PIC16F873

About The Author

Ibrar Ayyub

I am an experienced technical writer holding a Master's degree in computer science from BZU Multan, Pakistan University. With a background spanning various industries, particularly in home automation and engineering, I have honed my skills in crafting clear and concise content. Proficient in leveraging infographics and diagrams, I strive to simplify complex concepts for readers. My strength lies in thorough research and presenting information in a structured and logical format.

Follow Us:
LinkedinTwitter