Code for 'Smart Regulator' featured in 'Model Engineer', November 2020 on. Contains all work to August 2020 including all code described. Top level algorithm development is quite spares, leaving some work for you! Any questions - jon@jons-workshop.com

Dependencies:   mbed BufferedSerial Servo2 PCT2075 I2CEeprom FastPWM

cli.cpp

Committer:
JonFreeman
Date:
2019-06-28
Revision:
0:77803b3ee157
Child:
1:450090bdb6f4

File content as of revision 0:77803b3ee157:

/*
Command Line Interpreter code module.
Purpose -
    Provides easy interface to pc terminal programme for use during programme development, debug etc.
    Also usable as comms subsystem in finished code for accepting commands, reporting data etc.
*/
#include "mbed.h"
#include "Alternator.h"
//#include "BufferedSerial.h"
#include <cctype>
using namespace std;

extern  eeprom_settings     mode     ;
//eeprom_settings     mode     ;

extern  int ver, vef, measured_pw_us;
extern  uint32_t    ReadEngineRPM  ()   ;
extern  double  Read_BatteryVolts   ()  ;





const   int MAX_PARAMS = 10;
struct  parameters  {
    int32_t times[50];
    int32_t position_in_list, last_time, numof_dbls;
    double  dbl[MAX_PARAMS];
}   ;

//  WithOUT RTOS
//extern  BufferedSerial pc;
extern  Serial pc;
//extern  BufferedSerial pc;
extern  double  test_pot;    //  These used in knifeandfork code testing only

//extern  int numof_eeprom_options2    ;
//extern  struct  optpar const option_list2[]  ;
extern  struct optpar  option_list2[]    ;

/**void    mode_cmd (struct parameters & a)       //  With no params, reads eeprom contents. With params sets eeprom contents
*   mode_cmd called only from pc comms. No sense calling from Touch Screen Controller
*
*   Called without parameters - Lists to pc terminal current settings
*
*/
void    mode19_cmd (struct parameters & a)       //  With no params, reads eeprom contents. With params sets eeprom contents
{
    char            temps[36];
    int i;
    pc.printf   ("\r\nmode - Set system data in EEPROM - Jan 2019\r\nSyntax 'mode' with no parameters lists current state.\r\n");
    if  (a.numof_dbls)  {           //  If more than 0 parameters supplied
        for (i = 0; i < a.numof_dbls; i++)
            temps[i] = (char)a.dbl[i];          //  recast doubles to char
        while   (i < 33)
            temps[i++] = 0;
        i = (int)a.dbl[0];
        switch  (i) {
            case    0:    case    1:    case    2:    case    3:    case    4:
            case    5:    case    6:    case    7:    case    8:
                if  (temps[1] >= option_list2[i].min && temps[1] <= option_list2[i].max)
                    mode.wr(temps[1], RPM0 + i);
                break;
            case    37: //  set pwm scale factor
                if  (temps[1] >= option_list2[PWM_SCALE].min && temps[1] <= option_list2[PWM_SCALE].max)
                    mode.wr(temps[1], PWM_SCALE);
                break;
            case    83: //  set to defaults
                mode.set_defaults   ();
                break;
            case    9:      //  9 Save settings
                mode.save   ();
                pc.printf   ("Saving settings to EEPROM\r\n");
                break;
            default:
                break;
        }       //  endof   switch
    }           //  endof   //  If more than 0 parameters supplied
    else    {
        pc.printf   ("No Changes\r\n");
    }
    pc.printf   ("mode 0\t%s, [%d]\r\n", option_list2[0].t, mode.rd(RPM0));
    pc.printf   ("mode 1\t%s, [%d]\r\n", option_list2[1].t, mode.rd(RPM1));
    pc.printf   ("mode 2\t%s, [%d]\r\n", option_list2[2].t, mode.rd(RPM2));
    pc.printf   ("mode 3\t%s, [%d]\r\n", option_list2[3].t, mode.rd(RPM3));
    pc.printf   ("mode 4\t%s, [%d]\r\n", option_list2[4].t, mode.rd(RPM4));
    pc.printf   ("mode 5\t%s, [%d]\r\n", option_list2[5].t, mode.rd(RPM5));
    pc.printf   ("mode 6\t%s, [%d]\r\n", option_list2[6].t, mode.rd(RPM6));
    pc.printf   ("mode 7\t%s, [%d]\r\n", option_list2[7].t, mode.rd(RPM7));
    pc.printf   ("mode 8\t%s, [%d]\r\n", option_list2[8].t, mode.rd(RPM8));

    pc.printf   ("mode 37\t%s, [%d]\r\n", option_list2[PWM_SCALE].t, mode.rd(PWM_SCALE));
    pc.printf   ("mode 83\tSet to defaults\r\n");
    pc.printf   ("mode 9\tSave settings\r\r\n");

}

void    gpcmd   (struct parameters & a)   {
    pc.printf   ("pwm=%d\r\n", mode.get_pwm    ((int)a.dbl[0]));
}

void    rfcmd   (struct parameters & a)   {
    pc.printf   ("ver = %d, vef = %d, measured_pw_us = %d\r\n", ver, vef, measured_pw_us);
}

extern  double  glob_rpm;
extern  void    set_RPM_demand  (uint32_t   d)  ;

void    set_rpm_cmd   (struct parameters & a)   {
    pc.printf   ("setting RPM to %d\r\n",(int)a.dbl[0]);
    set_RPM_demand  ((uint32_t)a.dbl[0]);
}

void    speedcmd   (struct parameters & a)   {
    int s = ReadEngineRPM  ();
    pc.printf   ("speed %d, %.2f, pwm %d\r\n", s, glob_rpm, mode.get_pwm(s));
}

void    vcmd    (struct parameters & a)   {
    pc.printf   ("volts %.2f\r\n", Read_BatteryVolts());
}

extern  void    set_servo   (double p)  ;   //  Only for test, called from cli

void    set_servo_cmd    (struct parameters & a)   {
    double p = a.dbl[0] / 100.0;
    pc.printf   ("servo %.2f\r\n", p);
    set_servo   (p);
}

void    null_cmd (struct parameters & a)   {
    pc.printf   ("At null_cmd, parameters : First %.3f, second %.3f\r\n", a.dbl[0], a.dbl[1]);
}

void    menucmd (struct parameters & a);

struct kb_command  {
    const char * cmd_word;         //  points to text e.g. "menu"
    const char * explan;
    void (*f)(struct parameters &);   //  points to function
}  ;

struct  kb_command const command_list[] = {
    {"?", "Lists available commands, same as ls", menucmd},
    {"ls", "Lists available commands, same as menu", menucmd},
    {"rf", "Check rise and fall on VEXT", rfcmd},
    {"s", "Speed, RPM", speedcmd},
    {"v", "Read Battery volts", vcmd},
    {"gp","Get pwm from RPM", gpcmd},
    {"mode", "See or set eeprom values", mode19_cmd},
    {"nu", "do nothing", null_cmd},
    {"ser","set throttle servo direct 0 - 99", set_servo_cmd},
    {"sv","set engine RPM demand 3000 - 6000", set_rpm_cmd},
};

const int numof_menu_items = sizeof(command_list) / sizeof(kb_command);
void    menucmd (struct parameters & a)
{
    pc.printf("\r\nIntelligent Alternator Controller - Jon Freeman 2019\r\nAt menucmd function - listing commands:-\r\n");
    for(int i = 0; i < numof_menu_items; i++)
        pc.printf("[%s]\t\t%s\r\n", command_list[i].cmd_word, command_list[i].explan);
    pc.printf("End of List of Commands\r\n");
}

void    command_line_interpreter    ()
{
    const int MAX_CMD_LEN = 120;
    static  char    cmd_line[MAX_CMD_LEN + 4];
    static  int     cl_index = 0;
    int ch;
    char * pEnd;
    static struct  parameters  param_block  ;
    while  (pc.readable()) {
        ch = tolower(pc.getc());
       // pc.printf("%c", ch);
        if  (cl_index > MAX_CMD_LEN)  {   //  trap out stupidly long command lines
            pc.printf   ("Error!! Stupidly long cmd line\r\n");
            cl_index = 0;
        }
        if  (ch == '\r' || ch >= ' ' && ch <= 'z')
            pc.printf("%c", ch);
        else    {                   //  Using <Ctrl>+ 'F', 'B' for Y, 'L', 'R' for X, 'U', 'D' for Z
            cl_index = 0;           //                 6    2          12   18         21   4
            pc.printf("[%d]", ch);
            //nudger  (ch); //  was used on cnc to nudge axes a tad
        }
        if(ch != '\r')  //  was this the 'Enter' key?
            cmd_line[cl_index++] = ch;  //  added char to command being assembled
        else    {   //  key was CR, may or may not be command to lookup
            cmd_line[cl_index] = 0; //  null terminate command string
            if(cl_index)    {   //  If have got some chars to lookup
                int i, wrdlen;
                for (i = 0; i < numof_menu_items; i++)   {   //  Look for input match in command list
                    wrdlen = strlen(command_list[i].cmd_word);
                    if(strncmp(command_list[i].cmd_word, cmd_line, wrdlen) == 0 && !isalpha(cmd_line[wrdlen]))  {   //  If match found
                        for (int k = 0; k < MAX_PARAMS; k++)    {
                            param_block.dbl[k] = 0.0;
                        }
                        param_block.position_in_list = i;
                        param_block.last_time = clock    ();
                        param_block.numof_dbls = 0;
                        pEnd = cmd_line + wrdlen;
                        while   (*pEnd)  {          //  Assemble all numerics as doubles
                            param_block.dbl[param_block.numof_dbls++] = strtod    (pEnd, &pEnd);
                            while   (*pEnd && !isdigit(*pEnd) && '-' != *pEnd && '+' != *pEnd)  {   
                                pEnd++;
                            }
                        }
                        pc.printf   ("\r\n");
//                        for (int k = 0; k < param_block.numof_dbls; k++)
//                            pc.printf   ("Read %.3f\r\n", param_block.dbl[k]);
                        param_block.times[i] = clock();
                        command_list[i].f(param_block);   //  execute command
                        i = numof_menu_items + 1;    //  to exit for loop
                    }   //  end of match found
                }       // End of for numof_menu_items
                if(i == numof_menu_items)
                    pc.printf("No Match Found for CMD [%s]\r\n", cmd_line);
            }           //  End of If have got some chars to lookup
            pc.printf("\r\n>");
            cl_index = 0;
        }               // End of else key was CR, may or may not be command to lookup
    }                   //  End of while (pc.readable())
}