brewco/setup.c

Sun, 06 Dec 2015 14:29:37 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Sun, 06 Dec 2015 14:29:37 +0100
changeset 448
7fe45f6e4f48
parent 447
b48368855ec4
child 449
1277fb94999f
permissions
-rw-r--r--

Added PID editor.

/*****************************************************************************
 * Copyright (C) 2015
 *   
 * Michiel Broek <mbroek at mbse dot eu>
 *
 * This file is part of the mbsePi-apps
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * mbsePi-apps is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ThermFerm; see the file COPYING.  If not, write to the Free
 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *****************************************************************************/

#include "brewco.h"
#include "slcd.h"
#include "setup.h"
#include "prompt.h"
#include "xutil.h"
#include "keyboard.h"
#include "rdconfig.h"


extern int		my_shutdown;
extern int              debug;
extern sys_config       Config;
extern int              lcdHandle;
extern int		slcdHandle;



void editFloat(float *value, float low, float high, char *text)
{
    int		key;
    float	new = *value;
    char	pmpt[81];

    prompt(0, NULL);
    prompt(133, NULL);

    for (;;) {
	snprintf(pmpt, Config.lcd_cols + 1, "%s: %5.1f\001", text, new);
	prompt(200, pmpt);
	if (new == low)
	    prompt(404, NULL);
	else if (new == high)
	    prompt(402, NULL);
	else
	    prompt(403, NULL);

	key = keywait();
	if ((key == KEY_RETURN) || my_shutdown)
	    return;
	if (key == KEY_UP) {
	    new = new + 0.5;
	    if (new > high)
		new = high;
	}
	if (key == KEY_DOWN) {
	    new = new - 0.5;
	    if (new < low)
		new = low;
	}
	if (key == KEY_ENTER) {
	    *value = new;
	    return;
	}
    }
}



void editDouble(double *value, double low, double high, char *text)
{
    int         key;
    double	new = *value;
    char        pmpt[81];

    prompt(0, NULL);
    prompt(138, NULL);

    for (;;) {
        snprintf(pmpt, Config.lcd_cols + 1, "%s: %5.2lf", text, new);
        prompt(200, pmpt);
        if (new == low)
            prompt(404, NULL);
        else if (new == high)
            prompt(402, NULL);
        else
            prompt(403, NULL);

        key = keywait();
        if ((key == KEY_RETURN) || my_shutdown)
            return;
        if (key == KEY_UP) {
            new = new + 0.5;
            if (new > high)
                new = high;
        }
        if (key == KEY_DOWN) {
            new = new - 0.5;
            if (new < low)
                new = low;
        }
        if (key == KEY_ENTER) {
            *value = new;
            return;
        }
    }
}



void editInteger(int *value, int low, int high, int step, char *text, char *text2)
{
    int         key, new = *value;
    char        pmpt[81];

    prompt(0, NULL);
    prompt(134, NULL);

    for (;;) {
        snprintf(pmpt, Config.lcd_cols + 1, "%s: %3d %s", text, new, text2);
        prompt(200, pmpt);
        if (new == low)
            prompt(404, NULL);
        else if (new == high)
            prompt(402, NULL);
        else
            prompt(403, NULL);

        key = keywait();
        if ((key == KEY_RETURN) || my_shutdown)
            return;
        if (key == KEY_UP) {
            new += step;
            if (new > high)
                new = high;
        }
        if (key == KEY_DOWN) {
            new -= step;
            if (new < low)
                new = low;
        }
        if (key == KEY_ENTER) {
            *value = new;
            return;
        }
    }
}



void togglePmpts(int *value, char *text, int pno, char *pmpt1, char *pmpt2)
{
    int		key, new = *value;
    char	pmpt[81];

    prompt(0, NULL);
    prompt(pno, NULL);

    for (;;) {

        snprintf(pmpt, Config.lcd_cols + 1, "%s: %s", text, new ? pmpt1:pmpt2);
	prompt(200, pmpt);
	if (new) {
	    prompt(404, NULL);
	} else {
	    prompt(402, NULL);
	}

	key = keywait();
	if ((key == KEY_RETURN) || my_shutdown)
	    return;
	if ((key == KEY_UP) && new)
	    new = 0;
	else if ((key == KEY_DOWN) && (new == 0))
	    new = 1;
	if (key == KEY_ENTER) {
	    *value = new;
	    return;
	}
    }
}



void toggleYesNo(int *value, char *text)
{
    togglePmpts(value, text, 132, (char *)"Yes", (char *)"No ");
}



void toggleDirection(int *value, char *text)
{
    togglePmpts(value, text, 137, (char *)"Reverse", (char *)"Direct ");
}



void editPID(pid_var *pid)
{
    int		index = 1, key, val;
    char	pmpt[81];
    double	Kp, Ki, Kd;

    if (debug)
	fprintf(stdout, "editPID()\n");

    for (;;) {
	prompt(0, NULL);
	prompt(135, NULL);

	if (index == 1)
	    prompt(402, NULL);
	else if (index == 5)
	    prompt(404, NULL);
	else
	    prompt(403, NULL);

	switch (index) {
	    case 1:	snprintf(pmpt, Config.lcd_cols + 1, "PID Kp: %5.2f", PID_getKp(pid));
			break;
	    case 2:	snprintf(pmpt, Config.lcd_cols + 1, "PID Ki: %5.2f", PID_getKi(pid));
			break;
	    case 3:	snprintf(pmpt, Config.lcd_cols + 1, "PID Kd: %5.2f", PID_getKd(pid));
			break;
	    case 4:	snprintf(pmpt, Config.lcd_cols + 1, "SampleTime: %3d mSec", PID_getSampleTime(pid));
			break;
	    case 5:	snprintf(pmpt, Config.lcd_cols + 1, "Direction: %s", PID_getDirection(pid) ? (char *)"Reverse" : (char *)"Direct");
			break;
	}
	prompt(200, pmpt);

    	key = keywait();
    	if ((key == KEY_RETURN) || my_shutdown) {
	    if (debug)
	    	fprintf(stdout, "End editPID\n");
	    return;
    	}

    	if ((key == KEY_UP) && (index > 1))
	    index--;
    	if ((key == KEY_DOWN) && (index < 5))
	    index++;

    	if (key == KEY_ENTER) {

	    Kp = PID_getKp(pid);
	    Ki = PID_getKi(pid);
	    Kd = PID_getKd(pid);

	    switch(index) {
		case 1:	editDouble(&Kp, 0.5, 50, (char *)"PID Kp");
			PID_setTunings(pid, Kp, Ki, Kd);
			break;
		case 2:	editDouble(&Ki, 0.5, 50, (char *)"PID Ki");
			PID_setTunings(pid, Kp, Ki, Kd);
			break;
		case 3:	editDouble(&Kd, 0.5, 50, (char *)"PID Kd");
			PID_setTunings(pid, Kp, Ki, Kd);
			break;
		case 4: val = PID_getSampleTime(pid);
			editInteger(&val, 50, 500, 10, (char *)"SampleTime", (char *)"mSec");
			PID_setSampleTime(pid, val);
			break;
		case 5:	val = PID_getDirection(pid);
			toggleDirection(&val, (char *)"Direction");
			PID_setDirection(pid, val);
			break;
	    }
    	}
    }
}



/*
 * Edit a single unit
 */
void editUnit(units_list *unit)
{
    int		index = 1, key;
    char	pmpt[81];
    uLong	ocrc, ncrc;

    if (debug)
    	fprintf(stdout, "Start edit brewsystem %d %s\n", unit->number, unit->uuid);

    prompt(0, NULL);
    ncrc = ocrc = crc32(0L, Z_NULL, 0);
    ocrc = crc32(ocrc, (const Bytef *) unit, sizeof(units_list));

    for (;;) {

	prompt(0, NULL);
	prompt(131, NULL);

	if (index == 1)
	    prompt(402, NULL);
	else if (index == 21)
	    prompt(404, NULL);
	else
	    prompt(403, NULL);

	switch (index) {				//   12345678901234567890
	    case 1:	snprintf(pmpt, Config.lcd_cols + 1, "Unit name:");
			prompt(200, pmpt);
			snprintf(pmpt, Config.lcd_cols + 1, "%s", unit->name);
			prompt(300, pmpt);
			break;
	    case 2:	snprintf(pmpt, Config.lcd_cols + 1, "  HLT sensor setup");
			prompt(200, pmpt);
			break;
	    case 3:	snprintf(pmpt, Config.lcd_cols + 1, "  HLT heater setup");
			prompt(200, pmpt);
			break;
	    case 4:	snprintf(pmpt, Config.lcd_cols + 1, "  MLT sensor setup");
			prompt(200, pmpt);
			break;
	    case 5:	snprintf(pmpt, Config.lcd_cols + 1, "  MLT heater setup");
			prompt(200, pmpt);
			break;
	    case 6:	snprintf(pmpt, Config.lcd_cols + 1, "   MLT pump setup");
			prompt(200, pmpt);
			break;
	    case 7:	snprintf(pmpt, Config.lcd_cols + 1, "MLT heat b4 HLT: %s", unit->hlt_heater_mltfirst ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 8:	snprintf(pmpt, Config.lcd_cols + 1, "Pump cycle: %3d mins", unit->pump_cycle);
			prompt(200, pmpt);
			break;
	    case 9:	snprintf(pmpt, Config.lcd_cols + 1, "Pump rest : %3d mins", unit->pump_rest);
			prompt(200, pmpt);
			break;
	    case 10:	snprintf(pmpt, Config.lcd_cols + 1, " Pump pre-mash: %s", unit->pump_premash ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 11:	snprintf(pmpt, Config.lcd_cols + 1, " Pump on-mash: %s", unit->pump_onmash ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 12:	snprintf(pmpt, Config.lcd_cols + 1, " Pump mashout: %s", unit->pump_mashout ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 13:	snprintf(pmpt, Config.lcd_cols + 1, " Pump on-boil: %s", unit->pump_onboil ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 14:	snprintf(pmpt, Config.lcd_cols + 1, " Pump stop: %5.1f\001", unit->pump_stop);
			prompt(200, pmpt);
			break;
	    case 15:	snprintf(pmpt, Config.lcd_cols + 1, "    Skip Add: %s", unit->skip_add ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 16:	snprintf(pmpt, Config.lcd_cols + 1, "  Skip Remove: %s", unit->skip_remove ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 17:	snprintf(pmpt, Config.lcd_cols + 1, "  Skip Iodine: %s", unit->skip_iodine ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 18:	snprintf(pmpt, Config.lcd_cols + 1, "Iodine time: %3d min", unit->iodine_time);
			prompt(200, pmpt);
			break;
	    case 19:	snprintf(pmpt, Config.lcd_cols + 1, "   Whirlpool: %s", unit->whirlpool ? (char *)"Yes":(char *)"No");
			prompt(200, pmpt);
			break;
	    case 20:	snprintf(pmpt, Config.lcd_cols + 1, "   HLT PID setup");
			prompt(200, pmpt);
			break;
	    case 21:	snprintf(pmpt, Config.lcd_cols + 1, "   MLT PID setup");
			prompt(200, pmpt);
			break;
	}

	key = keywait();
	if ((key == KEY_RETURN) || my_shutdown) {
	    ncrc = crc32(ncrc, (const Bytef *)unit, sizeof(units_list));
	    if (ocrc != ncrc)
		wrconfig();
	    if (debug)
		fprintf(stdout, "End edit brewsystem %d %s\n", unit->number, unit->uuid);
	    return;
	}

	if ((key == KEY_UP) && (index > 1))
	    index--;
	if ((key == KEY_DOWN) && (index < 21))
	    index++;

	if (key == KEY_ENTER) {
	    switch(index) {
		case 1:		// name
				break;
		case 2:		// HLT sensor
				break;
		case 3:		// HLT heater
				break;
		case 4:		// MLT sensor
				break;
		case 5:		// MLT heater
				break;
		case 6:		// MLT pump
				break;
		case 7:		toggleYesNo(&unit->hlt_heater_mltfirst, (char *)"MLT heat b4 HLT");
				break;
		case 8:		editInteger(&unit->pump_cycle, 5, 15, 1, (char *)"Pump cycle", (char *)"mins");
				break;
		case 9:		editInteger(&unit->pump_rest, 1, 5, 1, (char *)"Pump rest ", (char *)"mins");
				break;
		case 10:	toggleYesNo(&unit->pump_premash, (char *)" Pump pre-mash");
				break;
		case 11:	toggleYesNo(&unit->pump_onmash, (char *)" Pump on-mash");
				break;
		case 12:	toggleYesNo(&unit->pump_mashout, (char *)" Pump mashout");
				break;
		case 13:	toggleYesNo(&unit->pump_onboil, (char *)" Pump on-boil");
				break;
		case 14:	editFloat(&unit->pump_stop, 80.0, 110.0, (char *)" Pump stop");
				break;
		case 15:	toggleYesNo(&unit->skip_add, (char *)"Skip add water");
				break;
		case 16:	toggleYesNo(&unit->skip_remove, (char *)"Skip remove Mash");
				break;
		case 17:	toggleYesNo(&unit->skip_iodine, (char *)"Skip iodine test");
				break;
		case 18:	editInteger(&unit->iodine_time, 10, 240, 10, (char *)"Iodine time", (char *)"min");
				break;
		case 19:	toggleYesNo(&unit->whirlpool, (char *)"Do a whirlpool");
				break;
		case 20:	editPID(unit->PID_hlt);
				break;
		case 21:	editPID(unit->PID_mlt);
				break;
	    }
	}
    }
}



void addUnit(int number)
{
    units_list	*tmpu, *unit = (units_list *)malloc(sizeof(units_list));
    char	name[81];
    uuid_t	uu;
    double	Input, Output, Setpoint;

    if (debug)
	fprintf(stdout, "Adding new brewsystem %d\n", number);
    unit->next = NULL;
    unit->version = 1;
    unit->uuid = malloc(37);
    uuid_generate(uu);
    uuid_unparse(uu, unit->uuid);
    snprintf(name, 20, "System %d", number);
    unit->name = xstrcpy(name);
    unit->number = number;
    if (number == 1)
	unit->active = 1;
    else
	unit->active = 0;
    unit->hlt_sensor = unit->mlt_sensor = NULL;
    unit->hlt_heater = unit->mlt_heater = unit->mlt_pump = NULL;
    unit->hlt_heater_mltfirst = 1;
    unit->pump_cycle = 7;
    unit->pump_rest = 2;
    unit->pump_premash = 1;
    unit->pump_onmash = 1;
    unit->pump_mashout = 0;
    unit->pump_onboil = 0;
    unit->pump_stop = 90;
    unit->skip_add = 0;
    unit->skip_remove = 0;
    unit->skip_iodine = 0;
    unit->iodine_time = 90;
    unit->whirlpool = 1;
    unit->PID_hlt = (pid_var *)malloc(sizeof(pid_var));
    unit->PID_mlt = (pid_var *)malloc(sizeof(pid_var));
    Input = Setpoint = 20.0;
    Output = 0;
    PID_init(unit->PID_hlt, &Input, &Output, &Setpoint, 2, 5, 1, P_DIRECT);
    PID_init(unit->PID_mlt, &Input, &Output, &Setpoint, 2, 5, 1, P_DIRECT);

    editUnit(unit);

    if (Config.units == NULL) {
	Config.units = unit;
    } else {
	for (tmpu = Config.units; tmpu; tmpu = tmpu->next) {
	    if (tmpu->next == NULL) {
		tmpu->next = unit;
		break;
	    }
	}
    }
    syslog(LOG_NOTICE, "Brewsystem %d added to the configuration", number);
    if (debug)
	fprintf(stdout, "Brewsystem %d added to the configuration\n", number);
}



void setup(void)
{
    int		key, option = 202;

    for (;;) {
	if (debug)
	    fprintf(stdout, "setup() option=%d\n", option);
	prompt(0, NULL);
	prompt(102, NULL);
	prompt(option, NULL);
	if (option == 202)
	    prompt(402, NULL);
#ifdef USE_SIMULATOR
	else if (option == 205)
#else
	else if (option == 204)
#endif
	    prompt(404, NULL);
	else
	    prompt(403, NULL);

	key = keywait();

	if ((key == KEY_RETURN) || my_shutdown)
	    return;
	if ((key == KEY_UP) && (option > 202)) {
	    option--;
	}
#ifdef USE_SIMULATOR
	if ((key == KEY_DOWN) && (option < 205)) {
#else
	if ((key == KEY_DOWN) && (option < 204)) {
#endif
	    option++;
	}

	if (key == KEY_ENTER) {
	    switch(option) {
		case 202:	// recipes
				break;
		case 203:	editUnit(Config.units);	/* If more units, via a selector */
				break;
		case 204:	// devices
				break;
#ifdef USE_SIMULATOR
		case 205:	// simulator
				break;
#endif
	    }
	    if (my_shutdown)
		return;
	}
    }
}

mercurial