Zsolt Pozsár
Published © CC BY-NC

How to connect Mini serial console to MM8D device

This is the first application of the Mini serial console device.

IntermediateFull instructions provided8 hours80
How to connect Mini serial console to MM8D device

Things used in this project

Story

Read more

Code

mini_serial_console-mm8d.ino

C/C++
Operation program
// +---------------------------------------------------------------------------+
// | Mini serial console for MM8D * v0.1                                       |
// | Copyright (C) 2022 Pozsár Zsolt <pozsarzs@gmail.com>                      |
// | mini_serial_console-mm8d.ino                                              |
// | Program for Raspberry Pi Pico                                             |
// +---------------------------------------------------------------------------+

/*
    This program is free software: you can redistribute it and/or modify it
  under the terms of the European Union Public License 1.2 version.

    This program 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.
*/

/*
  Operation modes
  ~~~~~~~~~~~~~~~

    Mode #0:   read only mode,
               no cursor,
               20x4 size displayed area on 80x4 size virtual screen,
               automatically scrolling lines,
               the displayed area can be moved horizontally with pushbuttons.
    Mode #1:   read only mode,
               no cursor,
               20x4 size displayed area on 80x25* size virtual screen,
               automatically scrolling lines,
               the displayed area can be moved horizontally and vertically with pushbuttons.
    Mode #2:   read only mode,
               no cursor,
               20x4 size displayed area on 80x25* size virtual screen,
               the displayed area can be moved horizontally and vertically with pushbuttons,
               after FormFeed (0x12), a new, clean page starts.
    Mode #3/0: read only mode,
               no cursor,
               20x4 size displayed area on 80x25* size virtual screen,
               the displayed page can be change with pushbuttons,
               switch to other submode with PB4 button.
    Mode #3/1: read only mode,
               no cursor,
               20x4 size displayed area on 80x25* size virtual screen,
               the displayed page can be change with pushbuttons,
               switch to other submode with PB4 button.
    Mode #3/2: read only mode,
               no cursor,
               20x4 size displayed area on 80x25* size virtual screen,
               automatically scrolling lines,
               the displayed area can be moved horizontally and vertically with
               pushbuttons,
               switch to other submode with PB4 button,
               lock scroll with PB5 button.

    Note:
     '*': You can set size of the virtual screen with virtscreenxsize and
          virtscreenysize constants in operation mode #1 and #2.


  Button functions
  ~~~~~~~~~~~~~~~~

    Button  Mode #0     Mode #1     Mode #2     Mode #3/0   Mode #3/1   Mode #3/2
    -------------------------------------------------------------------------------
     PB0    move left   move left   move left                           move left
     PB1    move right  move right  move right                          move right
     PB2                move up     move up     page up     page up     scroll up
     PB3                move down   move down   page down   page down   scroll down
     PB4                                        submode     submode     submode
     PB5                                                                lock scroll


  Serial ports
  ~~~~~~~~~~~~

    Serial0:  via USB port
    Serial1:  UART0  TTL    0/3.3V
    Serial2:  UART1  RS232  +/-12V


  Example incoming (binary) data lines in Mode #3
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

     0123456789ABC
    "CH..........."

    0:   'C'                                  0x43
    1:   'H'                                  0x48
    2:   number of channel                    0x00
    3:   overcurrent breaker error            0x00: closed 0x01: opened
    4:   water pump pressure error (no water) 0x00: good   0x01: bad
    5:   water pump pressure error (clogging) 0x00: good   0x01: bad
    6:   external temperature in °C          (0x00-0x80)
    7:   status of water pump and tube #1     0x00: off    0x01: on     0x02: always off 0x03: always on
    8:   status of water pump and tube #2     0x00: off    0x01: on     0x02: always off 0x03: always on
    9:   status of water pump and tube #3     0x00: off    0x01: on     0x02: always off 0x03: always on
    A-C: unused                               0x00

    0:   'C'                                  0x43
    1:   'H'                                  0x48
    2:   number of channel                    0x01-0x08
    3:   temperature in °C                   (0x00-0x80)
    4:   relative humidity                   (0x00-0x80)
    5:   relative unwanted gas concentrate   (0x00-0x80)
    6:   operation mode                       0x00: hyphae 0x01: mushr. 0x7F: disabled channel
    7:   manual mode                          0x00: auto   0x01: manual
    8:   overcurrent breaker error            0x00: closed 0x01: opened
    9:   status of door (alarm)               0x00: closed 0x01: opened
    A:   status of lamp output                0x00: off    0x01: on     0x02: always off 0x03: always on
    B:   status of ventilator output          0x00: off    0x01: on     0x02: always off 0x03: always on
    C:   status of heater output              0x00: off    0x01: on     0x02: always off 0x03: always on


  Example incoming (text) log lines in Mode #3
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

       0      1    2           3
    "221213 114421 I Configuration is loaded."
    "221213 114427 W CH2: MM6D is not accessible."
    "221213 114427 E ERROR #18: There is not enabled channel!"

    0:   date in yymmdd format
    1:   time in hhmmss format
    2:   level (information, warning, error)
    3:   short description
*/

#define LCD_8BIT                                            // enable 8 bit mode of the LCD
#define COM_USB                                             // enable Serial #0 port
#define COM_TTL                                             // enable Serial #1 port
#define COM_RS232C                                          // enable Serial #2 port
#define COM_USB_MESSAGES                                    // enable console messages on Serial #0 port
// #define COM_TTL_MESSAGES                                 // enable console messages on Serial #1 port
// #define COM_RS232C_MESSAGES                              // enable console messages on Serial #2 port
// #define TEST                                             // enable test mode of scrolling

#define BEL   0x07                                          // ASCII code of the control characters
#define TAB   0x09
#define FF    0x0B
#define SPACE 0x20
#define DEL   0x7F

#include <LiquidCrystal.h>

// settings
const int     lcd_bloffinterval       = 60000;              // LCD backlight off time after last button press
const byte    lcd_xsize               = 20;                 // horizontal size of display
const byte    lcd_ysize               = 4;                  // vertical size of display
const byte    virtscreenxsize         = 80;                 // horizontal size of virtual screen
const byte    virtscreenysize         = 25;                 // vertical size of virtual screen
// serial ports
const int     com_speed[3]            = {115200,
                                         9600,
                                         9600
                                        };                  // speed of the USB serial port
#ifdef ARDUINO_ARCH_MBED_RP2040
const byte    com_rxd2                = 8;
const byte    com_txd2                = 9;
#endif
// GPIO ports
const byte    lcd_bl                  = 14;                 // LCD - backlight on/off
const byte    lcd_db0                 = 2;                  // LCD - databit 0
const byte    lcd_db1                 = 3;                  // LCD - databit 1
const byte    lcd_db2                 = 4;                  // LCD - databit 2
const byte    lcd_db3                 = 5;                  // LCD - databit 3
const byte    lcd_db4                 = 10;                 // LCD - databit 4
const byte    lcd_db5                 = 11;                 // LCD - databit 5
const byte    lcd_db6                 = 12;                 // LCD - databit 6
const byte    lcd_db7                 = 13;                 // LCD - databit 7
const byte    lcd_en                  = 7;                  // LCD - enable
const byte    lcd_rs                  = 6;                  // LCD - register select
const byte    prt_jp2                 = 16;                 // operation mode (JP2 jumper)
const byte    prt_jp3                 = 15;                 // operation mode (JP3 jumper)
const byte    prt_pb0                 = 17;                 // pushbutton 0
const byte    prt_pb1                 = 18;                 // pushbutton 1
const byte    prt_pb2                 = 19;                 // pushbutton 2
const byte    prt_pb3                 = 20;                 // pushbutton 3
const byte    prt_pb4                 = 21;                 // pushbutton 4
const byte    prt_pb5                 = 22;                 // pushbutton 5
const byte    prt_led                 = LED_BUILTIN;        // LED on the board of Pico
byte          uparrow[8]              = {B00100,            // up arrow character for LCD
                                         B01110,
                                         B10101,
                                         B00100,
                                         B00100,
                                         B00100,
                                         B00100
                                        };
byte          downarrow[8]            = {B00100,            // down arrow character for LCD
                                         B00100,
                                         B00100,
                                         B00100,
                                         B10101,
                                         B01110,
                                         B00100
                                        };
// general constants
const String  swversion               = "0.1";              // version of this program
const int     btn_delay               = 200;                // time after read button status
// general variables
byte          virtoverridepagenum     = 0;                  // page num. for copy data (virtstatuspage->display)
byte          virtstatuspage[9][10];                        // virtual status pages
byte          virtstatuspagenum       = 0;                  // page num. for copy data (virtstatuspage->display)
char          virtscreen[virtscreenxsize][virtscreenysize]; // virtual screen
byte          virtscreenline          = 0;                  // y pos. for copy data (rxdbuffer->virtscreen)
byte          virtscreenxpos          = 0;                  // x pos. for copy data (virtscreen->display)
byte          virtscreenypos          = 0;                  // y pos. for copy data (virtscreen->display)
byte          virtscreenscrolllock    = 0;                  // lock autoscroll of the log
byte          operationmode;                                // operation mode of device
byte          operationsubmode        = 0;                  // sub operation mode of device in mode #3
unsigned long currenttime;                                  // current time
unsigned long previoustime            = 0;                  // last time of receiving or button pressing

// messages
String msg[28]                        = {"    MM8D console",               // 00
                                         "--------------------",           // 01
                                         "sw.: v",                         // 02
                                         "(C)2022 Pozsar Zsolt",           // 03
                                         "Initializing...",                // 04
                                         " * GPIO ports",                  // 05
                                         " * LCD",                         // 06
                                         " * Serial ports:",               // 07
                                         "operation mode: #",              // 08
                                         "Read a line from serial port #", // 09
                                         "Button pressed: PB",             // 10
                                         "Change to status pages",         // 11
                                         "Change to override pages",       // 12
                                         "Change to log page",             // 13
                                         "Lock autoscroll of log page",    // 14
                                         "STATUS",                         // 15
                                         "val",                            // 16
                                         "in",                             // 17
                                         "out",                            // 18
                                         "disabled channel",               // 19
                                         "OVERRIDE",                       // 20
                                         "tube #",                         // 21
                                         "neutral",                        // 22
                                         "    off",                        // 23
                                         "     on",                        // 24
                                         "lamp:      ",                    // 25
                                         "ventilator:",                    // 26
                                         "heater:    "                     // 27
                                        };

#ifdef ARDUINO_ARCH_MBED_RP2040
UART Serial2(com_rxd2, com_txd2, NC, NC);
#endif

#ifdef LCD_8BIT
LiquidCrystal lcd(lcd_rs, lcd_en, lcd_db0, lcd_db1, lcd_db2, lcd_db3, lcd_db4, lcd_db5, lcd_db6, lcd_db7);
#else
LiquidCrystal lcd(lcd_rs, lcd_en, lcd_db4, lcd_db5, lcd_db6, lcd_db7);
#endif

void com_writetoconsole(String message) {
#ifdef COM_USB_MESSAGES
  Serial.println(message);
#endif
#ifdef COM_TTL_MESSAGES
  Serial1.println(message);
#endif
#ifdef COM_RS232C_MESSAGES
  Serial2.println(message);
#endif
}

// LCD - turn on/off background light
void lcd_backlight(byte opmode) {
  switch (opmode) {
    case 0:
      digitalWrite(lcd_bl, LOW);
      break;
    case 1:
      digitalWrite(lcd_bl, HIGH);
      break;
    case 2:
      previoustime = millis();
      break;
    case 3:
      currenttime = millis();
      if (currenttime - previoustime >= lcd_bloffinterval) {
        digitalWrite(lcd_bl, LOW);
      } else {
        digitalWrite(lcd_bl, HIGH);
      }
      break;
  }
}

// copy selected virtual status page to LCD
void copyvirtstatuspage2lcd(byte page) {
  if (page == 0) {
    /*
        +--------------------+
        |CH #0  [  ]   STATUS|
        |val   T:00°C        |
        |in    BE:0 LP:0 HP:0|
        |out   T1:0 T2:0 T3:0|
        +--------------------+
    */
    lcd.clear();
    lcd.setCursor(0, 0); lcd.print("CH #" + String(page));
    lcd.setCursor(7, 0); lcd.print("[  ]");
    lcd.setCursor(8, 0); lcd.write(byte(0));
    lcd.setCursor(lcd_xsize - msg[15].length(), 0); lcd.print(msg[15]);
    lcd.setCursor(0, 1); lcd.print(msg[16]);
    lcd.setCursor(0, 2); lcd.print(msg[17]);
    lcd.setCursor(0, 3); lcd.print(msg[18]);
    lcd.setCursor(lcd_xsize - 14, 1);
    lcd.print("T:" + String(virtstatuspage[page][3]) + char(0xDF) + "C");
    lcd.setCursor(lcd_xsize - 14, 2);
    lcd.print("BE:" + String(virtstatuspage[page][0]) + " " +
              +"LP:" + String(virtstatuspage[page][1]) + " " +
              +"HP:" + String(virtstatuspage[page][2]));
    byte tube[3];
    for (byte b = 4; b < 7; b++) {
      tube[b - 4] = virtstatuspage[page][b];
      switch (virtstatuspage[page][b]) {
        case 0x02: tube[b - 4] = 0x00;
          break;
        case 0x03: tube[b - 4] = 0x01;
          break;
      }
    }
    lcd.setCursor(lcd_xsize - 14, 3);
    lcd.print("T1:" + String(tube[0]) + " " + "T2:" + String(tube[1]) + " " + "T3:" + String(tube[2]));
  } else {
    if (virtstatuspage[page][3] == 0x7F) {
      /*
          +--------------------+
          |CH #3  [  ]   STATUS|
          |                    |
          |  disabled channel  |
          |                    |
          +--------------------+
      */
      lcd.clear();
      lcd.setCursor(0, 0); lcd.print("CH #" + String(page));
      lcd.setCursor(7, 0); lcd.print("[  ]");
      if (page < 8) {
        lcd.setCursor(8, 0); lcd.write(byte(0));
      }
      lcd.setCursor(9, 0); lcd.write(byte(1));
      lcd.setCursor(lcd_xsize - msg[15].length(), 0); lcd.print(msg[15]);
      lcd.setCursor(lcd_xsize / 2 - msg[19].length() / 2, 2); lcd.print(msg[19]);
    } else {
      /*
          +--------------------+
          |CH #1  [  ]   STATUS|
          |val   T:00°C RH:100%|
          |in    OM:H CM:A BE:0|
          |out   LA:0 VE:0 HE:0|
          +--------------------+
      */
      lcd.clear();
      lcd.setCursor(0, 0); lcd.print("CH #" + String(page));
      lcd.setCursor(7, 0); lcd.print("[  ]");
      if (page < 8) {
        lcd.setCursor(8, 0); lcd.write(byte(0));
      }
      lcd.setCursor(9, 0); lcd.write(byte(1));
      lcd.setCursor(lcd_xsize - msg[15].length(), 0); lcd.print(msg[15]);
      lcd.setCursor(0, 1); lcd.print(msg[16]);
      lcd.setCursor(0, 2); lcd.print(msg[17]);
      lcd.setCursor(0, 3); lcd.print(msg[18]);
      lcd.setCursor(lcd_xsize - 14, 1);
      lcd.print("T:" + String(virtstatuspage[page][0]) + char(0xDF) + "C " +
                +"RH:" + String(virtstatuspage[page][1]) + "%");
      lcd.setCursor(lcd_xsize - 14, 2);
      String OM;
      String CM;
      OM = "?";
      CM = "?";
      switch (virtstatuspage[page][3]) {
        case 0x00:
          OM = 'H';
          break;
        case 0x01:
          OM = 'M';
          break;
        case 0x7F:
          OM = 'D';
          break;
      }
      switch (virtstatuspage[page][4]) {
        case 0x00:
          CM = 'A';
          break;
        case 0x01:
          CM = 'M';
          break;
      }
      lcd.print("OM:" + OM + " " + "CM:" + CM + " " + "BE:" + String(virtstatuspage[page][5]));
      byte out[3];
      for (byte b = 7; b < 10; b++) {
        out[b - 7] = virtstatuspage[page][b];
        switch (virtstatuspage[page][b]) {
          case 0x02: out[b - 7] = 0x00;
            break;
          case 0x03: out[b - 7] = 0x01;
            break;
        }
      }
      lcd.setCursor(lcd_xsize - 14, 3);
      lcd.print("LA:" + String(out[0]) + " " + "VE:" + String(out[1]) + " " + "HE:" + String(out[2]));
    }
  }
}

// clear virtual status pages
void clearvirtstatuspage() {
  for (byte y = 0; y <= 9; y++) {
    for (byte x = 0; x <= 8; x++) {
      virtstatuspage[x][y] = 0;
    }
  }
}

// copy selected virtual override page to LCD
void copyvirtoverridepage2lcd(byte page) {
  if (page == 0) {
    /*
        +--------------------+
        |CH #0  [  ] OVERRIDE|
        |tube #1:     neutral|
        |tube #2:     neutral|
        |tube #3:     neutral|
        +--------------------+
    */
    lcd.clear();
    lcd.setCursor(0, 0); lcd.print("CH #" + String(page));
    lcd.setCursor(7, 0); lcd.print("[  ]");
    lcd.setCursor(8, 0); lcd.write(byte(0));
    lcd.setCursor(lcd_xsize - msg[20].length(), 0); lcd.print(msg[20]);
    for (byte b = 1; b < 4; b++) {
      lcd.setCursor(0, b); lcd.print(msg[21] + String(b) + ":");
      lcd.setCursor(lcd_xsize - msg[22].length(), b);
      switch (virtstatuspage[page][b + 3]) {
        case 0x00: lcd.print(msg[22]);
          break;
        case 0x01: lcd.print(msg[22]);
          break;
        case 0x02: lcd.print(msg[23]);
          break;
        case 0x03: lcd.print(msg[24]);
          break;
      }
    }
  } else {
    /*
        +--------------------+
        |CH #1       OVERRIDE|
        |lamp:             on|
        |ventilator:  neutral|
        |heater:          off|
        +--------------------+
    */
    lcd.clear();
    lcd.setCursor(0, 0); lcd.print("CH #" + String(page));
    lcd.setCursor(7, 0); lcd.print("[  ]");
    if (page < 8) {
      lcd.setCursor(8, 0); lcd.write(byte(0));
    }
    lcd.setCursor(9, 0); lcd.write(byte(1));
    lcd.setCursor(lcd_xsize - msg[20].length(), 0); lcd.print(msg[20]);
    for (byte b = 1; b < 4; b++) {
      lcd.setCursor(0, b); lcd.print(msg[24 + b]);
      lcd.setCursor(lcd_xsize - msg[22].length(), b);
      switch (virtstatuspage[page][b + 6]) {
        case 0x00: lcd.print(msg[22]);
          break;
        case 0x01: lcd.print(msg[22]);
          break;
        case 0x02: lcd.print(msg[23]);
          break;
        case 0x03: lcd.print(msg[24]);
          break;
      }
    }
  }
}

// scroll up one line on virtual screen (log page in Mode #3)
void scroll(byte lastline) {
  if (virtscreenscrolllock == 0 ) {
    for (byte y = 1; y <= lastline; y++) {
      for (byte x = 0; x <= virtscreenxsize - 1; x++) {
        virtscreen[x][y - 1] = virtscreen[x][y];
        if (y == lastline) {
          virtscreen[x][y] = SPACE;
        }
      }
    }
  }
}

// copy text from virtual screen (log page in Mode #3) to LCD
void copyvirtscreen2lcd(byte x, byte y) {
  for (byte dy = 0; dy <= lcd_ysize - 1; dy++) {
    for (byte dx = 0; dx <= lcd_xsize - 1; dx++) {
      lcd.setCursor(dx, dy);
      lcd.write(virtscreen[x + dx][y + dy]);
    }
  }
}

// clear virtual screen (log page in Mode #3)
void clearvirtscreen() {
  for (byte y = 0; y <= virtscreenysize - 1; y++) {
    for (byte x = 0; x <= virtscreenxsize - 1; x++) {
      virtscreen[x][y] = SPACE;
    }
  }
}

// read communication port and move data to virtual screen
byte com_handler(byte port) {
  const byte rxdbuffersize       = 255;
  boolean newpage                = false;
  byte lastline;
  char rxdbuffer[rxdbuffersize];
  int rxdlength                  = 0;
  // read port and write to receive buffer
  switch (port) {
    case 0:
      if (Serial.available()) {
        digitalWrite(prt_led, HIGH);
        rxdlength = Serial.readBytes(rxdbuffer, rxdbuffersize);
        com_writetoconsole(msg[9] + String(port));
        digitalWrite(prt_led, LOW);
        // lcd_backlight(2);
      }
      break;
    case 1:
      if (Serial1.available()) {
        digitalWrite(prt_led, HIGH);
        rxdlength = Serial1.readBytes(rxdbuffer, rxdbuffersize);
        com_writetoconsole(msg[9] + String(port));
        digitalWrite(prt_led, LOW);
        // lcd_backlight(2);
      }
      break;
    case 2:
      if (Serial2.available()) {
        digitalWrite(prt_led, HIGH);
        rxdlength = Serial2.readBytes(rxdbuffer, rxdbuffersize);
        com_writetoconsole(msg[9] + String(port));
        digitalWrite(prt_led, LOW);
        // lcd_backlight(2);
      }
      break;
  }
  lcd_backlight(3);
  // check datalenght
  if (rxdlength > virtscreenxsize) {
    rxdlength = virtscreenxsize;
  }
  // copy line from receive buffer to virtual screen
  if (rxdlength) {
    switch (operationmode) {
      // in Mode #0
      case 0:
        lastline = 3;
        if (virtscreenline == lastline + 1) {
          scroll(lastline);
          virtscreenline = lastline;
        }
        for (byte b = 0; b < rxdlength; b++) {
          if (rxdbuffer[b] == BEL) {
            lcd_backlight(0);
            delay(250);
            lcd_backlight(1);
            delay(250);
            lcd_backlight(0);
            delay(250);
            lcd_backlight(1);
            delay(250);
            lcd_backlight(0);
            delay(250);
            lcd_backlight(1);
          }
          if (rxdbuffer[b] == TAB) {
            rxdbuffer[b] = SPACE;
          }
          if ((rxdbuffer[b] >= SPACE) and (rxdbuffer[b] < DEL)) {
            virtscreen[b][virtscreenline] = rxdbuffer[b];
          }
        }
        virtscreenline++;
        copyvirtscreen2lcd(virtscreenxpos, 0);
        break;
      // in Mode #1
      case 1:
        lastline = virtscreenysize - 1;
        if (virtscreenline == lastline + 1) {
          scroll(lastline);
          virtscreenline = lastline;
        }
        for (byte b = 0; b < rxdlength; b++) {
          if (rxdbuffer[b] == BEL) {
            lcd_backlight(0);
            delay(250);
            lcd_backlight(1);
            delay(250);
            lcd_backlight(0);
            delay(250);
            lcd_backlight(1);
            delay(250);
            lcd_backlight(0);
            delay(250);
            lcd_backlight(1);
          }
          if (rxdbuffer[b] == TAB) {
            rxdbuffer[b] = SPACE;
          }
          if ((rxdbuffer[b] >= SPACE) and (rxdbuffer[b] < DEL)) {
            virtscreen[b][virtscreenline] = rxdbuffer[b];
          }
        }
        virtscreenline++;
        copyvirtscreen2lcd(virtscreenxpos, virtscreenypos);
        break;
      // in Mode #2
      case 2:
        lastline = virtscreenysize - 1;
        if (virtscreenline == lastline + 1) {
          virtscreenline = 0;
        }
        for (byte b = 0; b < rxdlength; b++) {
          if (rxdbuffer[b] == BEL) {
            lcd_backlight(0);
            delay(250);
            lcd_backlight(1);
            delay(250);
            lcd_backlight(0);
            delay(250);
            lcd_backlight(1);
            delay(250);
            lcd_backlight(0);
            delay(250);
            lcd_backlight(1);
          }
          if (rxdbuffer[b] == TAB) {
            rxdbuffer[b] == SPACE;
          }
          if (rxdbuffer[b] == FF) {
            newpage = true;
          }
          if ((rxdbuffer[b] >= SPACE) and (rxdbuffer[b] < DEL)) {
            virtscreen[b][virtscreenline] = rxdbuffer[b];
          }
        }
        if (newpage) {
          clearvirtscreen();
          virtscreenline = 0;
          newpage = false;
        } else {
          virtscreenline++;
        }
        copyvirtscreen2lcd(virtscreenxpos, virtscreenypos);
        break;
      case 3:
        // in Mode #3
        if ((rxdbuffer[0] == 0x43) and (rxdbuffer[1] == 0x48)) // "CH"
        {
          for (byte b = 3; b < 13; b++) {
            virtstatuspage[rxdbuffer[2]][b - 3] = rxdbuffer[b];
          }
          if (operationsubmode < 2) {
            switch (operationsubmode) {
              case 0:
                copyvirtstatuspage2lcd(virtstatuspagenum);
                break;
              case 1:
                copyvirtoverridepage2lcd(virtoverridepagenum);
                break;
            }
          }
        } else
        {
          // if the received line is log
          lastline = virtscreenysize - 1;
          if (virtscreenline == lastline + 1) {
            scroll(lastline);
            virtscreenline = lastline;
          }
          for (byte b = 0; b < rxdlength; b++) {
            if (rxdbuffer[b] == BEL) {
              lcd_backlight(0);
              delay(250);
              lcd_backlight(1);
              delay(250);
              lcd_backlight(0);
              delay(250);
              lcd_backlight(1);
              delay(250);
              lcd_backlight(0);
              delay(250);
              lcd_backlight(1);
            }
            if (rxdbuffer[b] == TAB) {
              rxdbuffer[b] = SPACE;
            }
            if ((rxdbuffer[b] >= SPACE) and (rxdbuffer[b] < DEL)) {
              virtscreen[b][virtscreenline] = rxdbuffer[b];
            }
          }
          virtscreenline++;
          if (operationsubmode == 2) {
            copyvirtscreen2lcd(virtscreenxpos, virtscreenypos);
          }
        }
        break;
    }
  }
  return rxdlength;
}

// read status of pushbuttons and write text to LCD
void btn_handler(byte m, byte sm) {
  // horizontal move
  if ((m >= 0) and (m < 3)) {
    // [LEFT] button in Mode #0, #1 and #2
    if (not digitalRead(prt_pb0)) {
      com_writetoconsole(msg[10] + "0");
      delay(btn_delay);
      lcd_backlight(2);
      // move lines
      if (virtscreenxpos > 0) {
        virtscreenxpos--;
        copyvirtscreen2lcd(virtscreenxpos, virtscreenypos);
      }
    }
    // [RIGHT] button in Mode #0, #1 and #2
    if (not digitalRead(prt_pb1)) {
      com_writetoconsole(msg[10] + "1");
      delay(btn_delay);
      lcd_backlight(2);
      // move lines
      if (virtscreenxpos + lcd_xsize < virtscreenxsize) {
        virtscreenxpos++;
        copyvirtscreen2lcd(virtscreenxpos, virtscreenypos);
      }
    }
  }
  if (m == 3) {
    // [LEFT] button in Mode #3
    if (not digitalRead(prt_pb0)) {
      com_writetoconsole(msg[10] + "0");
      delay(btn_delay);
      lcd_backlight(2);
      switch (sm) {
        case 0:
          // SubMode #0: nothing
          break;
        case 1:
          // SubMode #1: nothing
          break;
        case 2:
          // SubMode #2: move lines
          if (virtscreenxpos > 0) {
            virtscreenxpos--;
            copyvirtscreen2lcd(virtscreenxpos, virtscreenypos);
          }
          break;
      }
    }
    // [RIGHT] button in Mode #3
    if (not digitalRead(prt_pb1)) {
      com_writetoconsole(msg[10] + "1");
      delay(btn_delay);
      lcd_backlight(2);
      switch (sm) {
        case 0:
          // SubMode #0: nothing
          break;
        case 1:
          // SubMode #1: nothing
          break;
        case 2:
          // SubMode #2: move lines
          if (virtscreenxpos + lcd_xsize < virtscreenxsize) {
            virtscreenxpos++;
            copyvirtscreen2lcd(virtscreenxpos, virtscreenypos);
          }
          break;
      }
    }
  }
  // vertical move
  if ((m > 0) and (m < 3)) {
    // [UP] button in Mode #0, #1 and #2
    if (not digitalRead(prt_pb2)) {
      com_writetoconsole(msg[10] + "2");
      delay(btn_delay);
      lcd_backlight(2);
      // scroll lines
      if (virtscreenypos > 0) {
        virtscreenypos--;
        copyvirtscreen2lcd(virtscreenxpos, virtscreenypos);
      }
    }
    // [DOWN] button in Mode #0, #1 and #2
    if (not digitalRead(prt_pb3)) {
      com_writetoconsole(msg[10] + "3");
      delay(btn_delay);
      lcd_backlight(2);
      // scroll lines
      if (virtscreenypos + lcd_ysize < virtscreenysize) {
        virtscreenypos++;
        copyvirtscreen2lcd(virtscreenxpos, virtscreenypos);
      }
    }
  }
  if (m == 3) {
    // [UP] button in Mode #3
    if (not digitalRead(prt_pb2)) {
      com_writetoconsole(msg[10] + "2");
      delay(btn_delay);
      lcd_backlight(2);
      switch (sm) {
        case 0:
          // SubMode #0: change page
          if (virtstatuspagenum > 0) {
            virtstatuspagenum--;
            copyvirtstatuspage2lcd(virtstatuspagenum);
          }
          break;
        case 1:
          // SubMode #1: change page
          if (virtoverridepagenum > 0) {
            virtoverridepagenum--;
            copyvirtoverridepage2lcd(virtoverridepagenum);
          }
          break;
        case 2:
          // SubMode #2: scroll lines
          if (virtscreenypos > 0) {
            virtscreenypos--;
            copyvirtscreen2lcd(virtscreenxpos, virtscreenypos);
          }
          break;
      }
    }
    // [DOWN] button in Mode #0, #1 and #2
    if (not digitalRead(prt_pb3)) {
      com_writetoconsole(msg[10] + "3");
      delay(btn_delay);
      lcd_backlight(2);
      switch (sm) {
        case 0:
          // SubMode #0: change page
          if (virtstatuspagenum < 8) {
            virtstatuspagenum++;
            copyvirtstatuspage2lcd(virtstatuspagenum);
          }
          break;
        case 1:
          // SubMode #1: change page
          if (virtoverridepagenum < 8) {
            virtoverridepagenum++;
            copyvirtoverridepage2lcd(virtoverridepagenum);
          }
          break;
        case 2:
          // SubMode #2: scroll lines
          if (virtscreenypos + lcd_ysize < virtscreenysize) {
            virtscreenypos++;
            copyvirtscreen2lcd(virtscreenxpos, virtscreenypos);
          }
          break;
      }
    }
  }
  // function buttons
  if (m == 3) {
    // [F1] button in Mode #3
    if (not digitalRead(prt_pb4)) {
      com_writetoconsole(msg[10] + "4");
      delay(btn_delay);
      lcd_backlight(2);
      // change SubMode and view actual page
      if (operationsubmode < 2) {
        operationsubmode++;
      } else {
        operationsubmode = 0;
      }
      lcd.clear();
      switch (operationsubmode) {
        case 0:
          copyvirtstatuspage2lcd(virtstatuspagenum);
          com_writetoconsole(msg[11]);
          break;
        case 1:
          copyvirtoverridepage2lcd(virtoverridepagenum);
          com_writetoconsole(msg[12]);
          break;
        case 2:
          virtscreenscrolllock = 0;
          copyvirtscreen2lcd(virtscreenxpos, virtscreenypos);
          com_writetoconsole(msg[13]);
          break;
      }
    }
    // [F2] button in Mode #3
    if (not digitalRead(prt_pb5)) {
      com_writetoconsole(msg[10] + "5");
      delay(btn_delay);
      lcd_backlight(2);
      // SubMode #2: lock autoscroll of the log
      if (operationsubmode == 2) {
        virtscreenscrolllock = not virtscreenscrolllock;
      }
      if (virtscreenscrolllock == 1) {
        com_writetoconsole(msg[14]);
      }
    }
  }
}
// get operation mode of device
byte getmode() {
  delay(250);
  return ((not digitalRead(prt_jp3)) * 2 + (not digitalRead(prt_jp2)));
}

// * * * MAIN FUNCTION * * *

// initializing
void setup() {
  String s;
  delay(3000);
  // serial ports
  Serial.begin(com_speed[0]);
  Serial1.begin(com_speed[1]);
  Serial2.begin(com_speed[2]);
  // write program information to console
  for (int b = 0; b <= 4; b++) {
    if (b == 2) {
      com_writetoconsole(msg[b] + swversion);
    } else {
      com_writetoconsole(msg[b]);
    }
  }
  // initializing I/O devices
  // GPIO ports
  com_writetoconsole(msg[5]);
  pinMode(lcd_bl, OUTPUT);
  pinMode(lcd_db0, OUTPUT);
  pinMode(lcd_db1, OUTPUT);
  pinMode(lcd_db2, OUTPUT);
  pinMode(lcd_db3, OUTPUT);
  pinMode(lcd_db4, OUTPUT);
  pinMode(lcd_db5, OUTPUT);
  pinMode(lcd_db6, OUTPUT);
  pinMode(lcd_db7, OUTPUT);
  pinMode(lcd_en, OUTPUT);
  pinMode(lcd_rs, OUTPUT);
  pinMode(prt_jp2, INPUT);
  pinMode(prt_jp3, INPUT);
  pinMode(prt_led, OUTPUT);
  pinMode(prt_pb0, INPUT);
  pinMode(prt_pb1, INPUT);
  pinMode(prt_pb2, INPUT);
  pinMode(prt_pb3, INPUT);
  pinMode(prt_pb4, INPUT);
  pinMode(prt_pb5, INPUT);
  // display
  com_writetoconsole(msg[6]);
  lcd.createChar(0, uparrow);
  lcd.createChar(1, downarrow);
  lcd.begin(lcd_xsize, lcd_ysize);
  lcd_backlight(1);
  lcd_backlight(2);
  // write program information to display
  for (int b = 0; b <= 3; b++) {
    lcd.setCursor(0, b);
    if (b == 2) {
      lcd.print(msg[b] + swversion);
    } else {
      lcd.print(msg[b]);
    }
  }
  delay(3000);
  lcd.clear();
  com_writetoconsole(msg[7]);
  for (int b = 0; b <= 2; b++) {
    s = "#" + String(b) + ": " + String(com_speed[b]) + " baud";
    com_writetoconsole("   " + s);
    lcd.setCursor(0, b); lcd.print(s);
  }
  // get operation mode
  operationmode = getmode();
  s = msg[8] + String(operationmode);
  com_writetoconsole(" * " + s);
  lcd.setCursor(0, 3); lcd.print(s);
  delay(3000);
  lcd.clear();
  // clean of fill data virtual screen and copy LCD
#ifdef TEST
  char ch = 33;
...

This file has been truncated, please download it to see its full contents.

mm8d-msctest.py

Python
Checker program
#!/usr/bin/python3
# +----------------------------------------------------------------------------+
# | MM8D v0.4 * Growing house and irrigation controlling and monitoring system |
# | Copyright (C) 2020-2022 Pozsar Zsolt <pozsar.zsolt@szerafingomba.hu>       |
# | mm8d-msctest.py                                                            |
# | Mini serial console test program                                           |
# +----------------------------------------------------------------------------+

#   This program is free software: you can redistribute it and/or modify it
# under the terms of the European Union Public License 1.1 version.
#
#   This program 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.

# Exit codes:
#   0: normal exit
#   1: cannot open configuration file

import configparser
import io
import os
import serial
import sys
import time
from time import localtime, strftime

USRLOCALDIR = 1
if (USRLOCALDIR == 1):
  conffile = '/usr/local/etc/mm8d/mm8d.ini'
else:
  conffile = '/etc/mm8d/mm8d.ini'

# write a debug log line to serial port
def writedebuglogtocomport(level,text):
  if com_enable == "1":
    dt = (strftime("%y%m%d %H%M%S",localtime()))
    try:
      com.open
      com.write(str.encode(dt + ' ' + str.upper(level) + ' ' + text + eol))
      com.close
    except:
      print("")

# send channels' data to display via serial port
def writechannelstatustocomport(channel):
  transmitbuffer = [0x00 for x in range(13)]
  line = ""
  if com_enable == "1":
    if channel == 0:
      transmitbuffer[0x00] = ord("C")
      transmitbuffer[0x01] = ord("H")
      transmitbuffer[0x02] = channel
      transmitbuffer[0x03] = mainsbreakers
      transmitbuffer[0x04] = waterpressurelow
      transmitbuffer[0x05] = waterpressurehigh
      transmitbuffer[0x06] = exttemp
      transmitbuffer[0x07] = relay_tube1
      transmitbuffer[0x08] = relay_tube2
      transmitbuffer[0x09] = relay_tube3
      transmitbuffer[0x0A] = 0x00
      transmitbuffer[0x0B] = 0x00
      transmitbuffer[0x0C] = 0x00
      if override[channel][0] == 2:
        transmitbuffer[0x07] = 0x03
      if override[channel][0] == 1:
        transmitbuffer[0x07] = 0x02
      if override[channel][1] == 2:
        transmitbuffer[0x08] = 0x03
      if override[channel][1] == 1:
        transmitbuffer[0x08] = 0x02
      if override[channel][2] == 2:
          transmitbuffer[0x09] = 0x03
      if override[channel][2] == 1:
          transmitbuffer[0x09] = 0x02
    else:
      transmitbuffer[0x00] = ord("C")
      transmitbuffer[0x01] = ord("H")
      transmitbuffer[0x02] = channel
      transmitbuffer[0x03] = in_temperature[channel]
      transmitbuffer[0x04] = in_humidity[channel]
      transmitbuffer[0x05] = in_gasconcentrate[channel]
      transmitbuffer[0x06] = in_opmode[channel]
      transmitbuffer[0x07] = in_swmanu[channel]
      transmitbuffer[0x08] = in_ocprot[channel]
      transmitbuffer[0x09] = in_alarm[channel]
      transmitbuffer[0x0A] = out_lamps[channel]
      transmitbuffer[0x0B] = out_vents[channel]
      transmitbuffer[0x0C] = out_heaters[channel]
      if override[channel][0] == 2:
        transmitbuffer[0x0A] = 0x03
      if override[channel][0] == 1:
        transmitbuffer[0x0A] = 0x02
      if override[channel][1] == 2:
        transmitbuffer[0x0B] = 0x03
      if override[channel][1] == 1:
        transmitbuffer[0x0B] = 0x02
      if override[channel][2] == 2:
          transmitbuffer[0x0C] = 0x03
      if override[channel][2] == 1:
          transmitbuffer[0x0C] = 0x02
  for x in range(0,13):
    line = line + chr(transmitbuffer[x])
  try:
    com.open
    com.write(str.encode(line))
    com.close
  except:
    print("")

# load configuration
def loadconfiguration(conffile):
  global com
  global com_device
  global com_speed
  global com_enable
  com_enable = "1"
  try:
    with open(conffile) as f:
      mm8d_config=f.read()
    config=configparser.RawConfigParser(allow_no_value=True)
    config.read_file(io.StringIO(mm8d_config))
    com_device=config.get('COMport','com_device')
    com_speed=int(config.get('COMport','com_speed'))
  except:
    print("ERROR #1: Cannot open configuration file!");
    sys.exit(1);

# main function
global channel
global ena_ch
global eol
global exttemp
global in_alarm
global in_gasconcentrate
global in_humidity
global in_ocprot
global in_opmode
global in_swmanu
global in_temperature
global mainsbreakers
global out_heaters
global out_lamps
global out_vents
global override
global ovrstatus
global relay_tube1
global relay_tube2
global relay_tube3
global waterpressurehigh
global waterpressurelow
channel = 0
ena_ch = [1 for channel in range(9)]
eol = "\r"
exttemp = 23
in_alarm = [0 for channel in range(9)]
in_gasconcentrate = [3 for channel in range(9)]
in_humidity = [75 for channel in range(9)]
in_ocprot = [0 for channel in range(9)]
in_opmode = [0 for channel in range(9)]
in_swmanu = [0 for channel in range(9)]
in_temperature = [18 for channel in range(9)]
mainsbreakers = 0
out_heaters = [0 for channel in range(9)]
out_lamps = [0 for channel in range(9)]
out_vents = [0 for channel in range(9)]
override = [[0 for x in range(3)] for x in range(9)]
ovrstatus = ["neutral","off","on"]
relay_tube1 = 0
relay_tube2 = 0
relay_tube3 = 0
waterpressurehigh = 0
waterpressurelow = 0

print("\nMM8D Mini serial console test utility * (C) 2020-2022 Pozsar Zsolt")
print("--------------------------------------------------------------------")
print(" * load configuration: %s..." % conffile)
loadconfiguration(conffile)
print(" * setting ports...")
com = serial.Serial(com_device, com_speed)

while True:
  print(" * What do you like?")
  menuitem = input(" \
   1: Set parameters of the Channel #0\n \
   2: Set parameters of the Channel #1-8\n \
   q: Quit\n")
  if menuitem is "Q" or menuitem is "q":
    break;
  if menuitem is "1":
    channel = 0
    while True:
      print(" * Set variables of the Channel #0")
      print("      channel               ",channel)
      print("   1: mainsbreakers         ",mainsbreakers)
      print("   2: waterpressurelow      ",waterpressurelow)
      print("   3: waterpressurehigh     ",waterpressurehigh)
      print("   4: exttemp               ",exttemp)
      print("   5: relay_tube1           ",relay_tube1)
      print("   6: relay_tube2           ",relay_tube2)
      print("   7: relay_tube3           ",relay_tube3)
      print("   8: override[" + str(channel) + "][0]        ",ovrstatus[override[channel][0]])
      print("   9: override[" + str(channel) + "][1]        ",ovrstatus[override[channel][1]])
      print("   a: override[" + str(channel) + "][2]        ",ovrstatus[override[channel][2]] + "\n")
      print("      Enable/disable CH #" + str(channel) + "  ",ena_ch[channel])
      print("   x: Send data")
      print("   q: Back to main menu")
      submenuitem = input()
      if submenuitem is "1":
        mainsbreakers = int(not mainsbreakers)
        if mainsbreakers == 1:
          writedebuglogtocomport("e","Overcurrent breaker is opened!")
      if submenuitem is "2":
        waterpressurelow = int(not waterpressurelow)
        if waterpressurelow == 1:
          writedebuglogtocomport("e","Pressure is too low after water pump!")
      if submenuitem is "3":
        waterpressurehigh = int(not waterpressurehigh)
        if waterpressurehigh == 1:
          writedebuglogtocomport("e","Pressure is too high after water pump!")
      if submenuitem is "4":
        exttemp = int(input("Enter new value (0-100): "))
        writedebuglogtocomport("i","External temperature: " + str(exttemp) + " degree Celsius")
      if submenuitem is "5":
         relay_tube1 = int(not relay_tube1)
         if relay_tube1 == 1:
           writedebuglogtocomport("i","CH0: Output water pump and valve #1 ON")
         else:
           writedebuglogtocomport("i","CH0: Output water pump and valve #1 OFF")
      if submenuitem is "6":
         relay_tube2 = int(not relay_tube2)
         if relay_tube2 == 1:
           writedebuglogtocomport("i","CH0: Output water pump and valve #2 ON")
         else:
           writedebuglogtocomport("i","CH0: Output water pump and valve #2 OFF")
      if submenuitem is "7":
         relay_tube3 = int(not relay_tube3)
         if relay_tube3 == 1:
           writedebuglogtocomport("i","CH0: Output water pump and valve #3 ON")
         else:
           writedebuglogtocomport("i","CH0: Output water pump and valve #3 OFF")
      if submenuitem is "8":
        override[channel][0] = override[channel][0] + 1
        if override[channel][0] == 3:
          override[channel][0] = 0
        if override[channel][0] == 2:
          writedebuglogtocomport("i","CH0: -> water pump and valve #1 ON")
        if override[channel][0] == 1:
          writedebuglogtocomport("i","CH0: -> water pump and valve #1 OFF")
      if submenuitem is "9":
        override[channel][1] = override[channel][1] + 1
        if override[channel][1] == 3:
          override[channel][1] = 0
        if override[channel][1] == 2:
          writedebuglogtocomport("i","CH0: -> water pump and valve #2 ON")
        if override[channel][1] == 1:
          writedebuglogtocomport("i","CH0: -> water pump and valve #2 OFF")
      if submenuitem is "a":
        override[channel][2] = override[channel][2] + 1
        if override[channel][2] == 3:
          override[channel][2] = 0
        if override[channel][2] == 2:
          writedebuglogtocomport("i","CH0: -> water pump and valve #3 ON")
        if override[channel][2] == 1:
          writedebuglogtocomport("i","CH0: -> water pump and valve #3 OFF")
      if submenuitem is "x":
        writechannelstatustocomport(channel)
      if submenuitem is "Q" or submenuitem is "q":
        break
  if menuitem is "2":
    channel = 1
    while True:
      print(" * Set variables of the Channel #1-8")
      print("   0: channel             ",channel)
      print("   1: in_temperature[" + str(channel) + "]   ",in_temperature[channel])
      print("   2: in_humidity[" + str(channel) + "]      ",in_humidity[channel])
      print("   3: in_gasconcentrate[" + str(channel) + "]",in_gasconcentrate[channel])
      print("   4: in_opmode[" + str(channel) + "]        ",in_opmode[channel])
      print("   5: in_swmanu[" + str(channel) + "]        ",in_swmanu[channel])
      print("   6: in_ocprot[" + str(channel) + "]        ",in_ocprot[channel])
      print("   7: in_alarm[" + str(channel) + "]         ",in_alarm[channel])
      print("   8: out_lamps[" + str(channel) + "]        ",out_lamps[channel])
      print("   9: out_vents[" + str(channel) + "]        ",out_vents[channel])
      print("   a: out_heaters[" + str(channel) + "]      ",out_heaters[channel])
      print("   b: override[" + str(channel) + "][0]      ",ovrstatus[override[channel][0]])
      print("   c: override[" + str(channel) + "][1]      ",ovrstatus[override[channel][1]])
      print("   d: override[" + str(channel) + "][2]      ",ovrstatus[override[channel][2]] + "\n")
      print("   y: Enable/disable CH #" + str(channel) + "",ena_ch[channel])
      print("   x: Send data")
      print("   q: Back to main menu")
      submenuitem = input()
      if submenuitem is "0":
        channel = channel + 1
        if channel == 9:
          channel = 1
      if submenuitem is "1":
        in_temperature[channel] = int(input("Enter new value (0-100): "))
        writedebuglogtocomport("i","CH" + str(channel) + ": Measured T is " + str(in_temperature[channel]) + " C")
      if submenuitem is "2":
        in_humidity[channel] = int(input("Enter new value (0-100): "))
        writedebuglogtocomport("i","CH" + str(channel) + ": Measured RH is " + str(in_humidity[channel]) + "%")
      if submenuitem is "3":
        in_gasconcentrate[channel] = int(input("Enter new value (0-100): "))
        writedebuglogtocomport("i","CH" + str(channel) + ": Measured RUGC is " + str(in_gasconcentrate[channel]) + "%")
      if submenuitem is "4":
        if in_opmode[channel] < 2:
          in_opmode[channel] = int(not in_opmode[channel])
          if in_opmode[channel] == 1:
            writedebuglogtocomport("i","CH" + str(channel) + ": Operation mode: growing hyphae.")
          else:
            writedebuglogtocomport("i","CH" + str(channel) + ": Operation mode: growing mushroom.")
      if submenuitem is "5":
        in_swmanu[channel] = int(not in_swmanu[channel])
        if in_swmanu[channel] == 1:
          writedebuglogtocomport("w","CH"+ str(channel) +": Manual mode switch is on position.")
      if submenuitem is "6":
        in_ocprot[channel] = int(not in_ocprot[channel])
        if in_ocprot[channel] == 1:
          writedebuglogtocomport("e","CH"+ str(channel) +": Overcurrent breaker of MM6D is opened!")
      if submenuitem is "7":
        in_alarm[channel] = int(not in_alarm[channel])
        if in_alarm[channel] == 1:
          writedebuglogtocomport("i","CH"+ str(channel) +": Alarm input of MM6D device is active.")
      if submenuitem is "8":
         out_lamps[channel] = int(not out_lamps[channel])
         if out_lamps[channel] == 1:
           writedebuglogtocomport("i","CH" + str(channel) + ": Output lamps ON")
         else:
           writedebuglogtocomport("i","CH" + str(channel) + ": Output lamps OFF")
      if submenuitem is "9":
         out_vents[channel] = int(not out_vents[channel])
         if out_vents[channel] == 1:
           writedebuglogtocomport("i","CH" + str(channel) + ": Output ventilators ON")
         else:
           writedebuglogtocomport("i","CH" + str(channel) + ": Output ventilators OFF")
      if submenuitem is "a":
         out_heaters[channel] = int(not out_heaters[channel])
         if out_heaters[channel] == 1:
           writedebuglogtocomport("i","CH" + str(channel) + ": Output heaters ON")
         else:
           writedebuglogtocomport("i","CH" + str(channel) + ": Output heaters OFF")
      if submenuitem is "b":
        override[channel][0] = override[channel][0] + 1
        if override[channel][0] == 3:
          override[channel][0] = 0
        if override[channel][0] == 2:
          writedebuglogtocomport("i","CH" + str(channel) + ": -> lamps ON")
        if override[channel][0] == 1:
          writedebuglogtocomport("i","CH" + str(channel) + ": -> lamps OFF")
      if submenuitem is "c":
        override[channel][1] = override[channel][1] + 1
        if override[channel][1] == 3:
          override[channel][1] = 0
        if override[channel][1] == 2:
          writedebuglogtocomport("i","CH" + str(channel) + ": -> ventilators ON")
        if override[channel][1] == 1:
          writedebuglogtocomport("i","CH" + str(channel) + ": -> ventilators OFF")
      if submenuitem is "d":
        override[channel][2] = override[channel][2] + 1
        if override[channel][2] == 3:
          override[channel][2] = 0
        if override[channel][2] == 2:
          writedebuglogtocomport("i","CH" + str(channel) + ": -> heaters ON")
        if override[channel][2] == 1:
          writedebuglogtocomport("i","CH" + str(channel) + ": -> heaters OFF")
      if submenuitem is "y":
        ena_ch[channel] = int(not ena_ch[channel])
        if ena_ch[channel] == 0:
          in_opmode[channel] = 127
        else:
          in_opmode[channel] = 0
      if submenuitem is "x":
        writechannelstatustocomport(channel)
      if submenuitem is "Q" or submenuitem is "q":
        break
sys.exit(0)

mm8d.ini

INI
Settings for mm8d-msctest.py
; +----------------------------------------------------------------------------+
; | MM8D v0.4 * Growing house and irrigation controlling and monitoring system |
; | Copyright (C) 2020-2022 Pozsr Zsolt <pozsar.zsolt@szerafingomba.hu>       |
; | mm8d.ini                                                                   |
; | Main settings                                                              |
; +----------------------------------------------------------------------------+

[user]
; user's data
usr_nam=Szerafin Gomba
usr_uid=00000000
usr_dt1=Gombakert
usr_dt2=5430 Tiszafoldvar, Kurazsi Fo ut 1.
usr_dt3=11-18. sator

[names]
; name of channels
nam_ch0=Irrigator
nam_ch1=Tent #11
nam_ch2=Tent #12
nam_ch3=Tent #13
nam_ch4=Tent #14
nam_ch5=Tent #15
nam_ch6=Tent #16
nam_ch7=Tent #17
nam_ch8=Tent #18

[enable]
; enable/disable channels
ena_ch1=1
ena_ch2=1
ena_ch3=0
ena_ch4=0
ena_ch5=0
ena_ch6=0
ena_ch7=0
ena_ch8=0

[MM6D]
; IP address of MM6D controllers
adr_mm6dch1=192.168.1.11
adr_mm6dch2=192.168.1.12
adr_mm6dch3=192.168.1.13
adr_mm6dch4=192.168.1.14
adr_mm6dch5=192.168.1.15
adr_mm6dch6=192.168.1.16
adr_mm6dch7=192.168.1.17
adr_mm6dch8=192.168.1.18

[MM7D]
; IP address of MM7D controllers
adr_mm7dch1=192.168.1.21
adr_mm7dch2=192.168.1.22
adr_mm7dch3=192.168.1.23
adr_mm7dch4=192.168.1.24
adr_mm7dch5=192.168.1.25
adr_mm7dch6=192.168.1.26
adr_mm7dch7=192.168.1.27
adr_mm7dch8=192.168.1.28

[GPIOports]
; number of used GPIO ports
prt_i1=12
prt_i2=16
prt_i3=20
prt_i4=21
prt_ro1=18
prt_ro2=23
prt_ro3=24
prt_ro4=25
prt_lo1=2
prt_lo2=3
prt_lo3=4
prt_lo4=17

[LPTport]
; address of used LPT port
; 0: 0x378
; 1: 0x278
; 2: 0x3BC
lpt_prt=0

[COMport]
; enable/disable external serial display
com_enable=1
; port name
com_device=/dev/ttyS0
; port speed
com_speed=9600

[directories]
; directories of program
dir_htm=/var/www/html
dir_lck=/var/local/lock
dir_log=/var/local/log
dir_msg=/usr/local/share/locale
dir_shr=/usr/local/share/mm8d
dir_tmp=/var/tmp
dir_var=/var/local/lib/mm8d

[openweathermap.org]
; access data
api_key=00000000000000000000000000000000
base_url=http://api.openweathermap.org/data/2.5/weather?
city_name=Tiszafoldvar

[IPcameras]
; camera of growing tents
; show camera picture on webpage
cam_show=0
; jpg snapshot link of IP cameras
cam_ch1=http://camera-th11.lan/snapshot.cgi?user=username&pwd=password
cam_ch2=http://camera-th12.lan/snapshot.cgi?user=username&pwd=password
cam_ch3=http://camera-th13.lan/snapshot.cgi?user=username&pwd=password
cam_ch4=http://camera-th14.lan/snapshot.cgi?user=username&pwd=password
cam_ch5=http://camera-th15.lan/snapshot.cgi?user=username&pwd=password
cam_ch6=http://camera-th16.lan/snapshot.cgi?user=username&pwd=password
cam_ch7=http://camera-th17.lan/snapshot.cgi?user=username&pwd=password
cam_ch8=http://camera-th18.lan/snapshot.cgi?user=username&pwd=password

[language]
; language of webpage (en/hu)
lng=en

[log]
; create and show log
; storing time of log
day_log=7
; enable/disable verbose debug log
dbg_log=0
; number of log lines on web interface
web_lines=30

Mini serial console for MM8D - software

Operation program in package

Software for MM8D device

Operation program in package

Credits

Zsolt Pozsár

Zsolt Pozsár

12 projects • 7 followers
I am not professional programmer, I specialize in electronics and electrical installation.

Comments