Відповісти

Введіть повідомлення і натисніть Надіслати
Параметри

Назад

Огляд теми (нові повідомленні вгорі)

NoName
2016-07-17 20:51:11

qwone, без примера,  фраза очень остра )
мы все из ANSI C89 )

source  www.rosettacode.org/

 
#include <iostream>
#include <string>
#include <sstream>
 
namespace bottle_song
{
  // =================================================================
 
  // ***********************************
  // * Abstract base class for things. *
  // ***********************************
 
  class thing
  {
  public:
    // return the singular of the thing
    virtual std::string singular() const = 0;
 
    // return the plural of the thing
    virtual std::string plural() const = 0;
 
    // we need a virtual destructor, too
    virtual ~thing() {}
  };
 
  // =================================================================
 
  // ***************
  // * Containers. *
  // ***************
 
  // Containers are things which can contain other things. The
  // following class makes any thing into a container. The container
  // class is actually a decorator which makes any thing into a
  // container. Note that the contained thing is actually mutable,
  // even if the container is not. Note that the container can only
  // contain a single thing; if it shall contain several things, make
  // it contain a collection instead.
 
  class container: public thing
  {
  public:
    // The format gives the name. %self% is replaced by the containing
    // object's name (in proper pluralization), %contained% is
    // replaced by the contained object's name.
    container(std::string fmt, thing const& what, thing const& contained);
    std::string singular() const;
    std::string plural() const;
  private:
    std::string format;
    thing const& self;
    thing const& contained_thing;
    // helper function to replace strings
    static void replace(std::string& str, std::string from, std::string to);
  };
 
  container::container(std::string fmt,
                       thing const& what,
                       thing const& contained):
    format(fmt),
    self(what),
    contained_thing(contained)
  {
  }
 
  std::string container::singular() const
  {
    std::string result = format;
    replace(result, "%self%", self.singular());
    replace(result, "%contained%", contained_thing.singular());
    return result;
  }
 
  std::string container::plural() const
  {
    std::string result = format;
    replace(result, "%self%", self.plural());
    replace(result, "%contained%", contained_thing.singular());
    return result;
  }
 
  void container::replace(std::string& str, std::string from, std::string to)
  {
    std::string::size_type pos = str.find(from);
    if (pos != std::string::npos)
      str.replace(pos, from.length(), to);
  }
  // =================================================================
 
  // *********************************
  // * A collection of equal things. *
  // *********************************
 
  // In the context of this program, a collection of things is again
  // considered a single thing.
  // This is a concrete class.
  class equal_collection: public thing
  {
  public:
    // constructor
    equal_collection(int count, thing const& what);
 
    // get singular
    std::string singular() const;
 
    // get plural. This has to be implemented, even if it isn't used,
    // because the inherited version is pure virtual, and not
    // implementing this would make the class abstract.
    std::string plural() const;
 
    // this just returns whether thwere are still things left to take away.
    bool there_is_some_left();
 
    // this takes one thing away from the collection. Taking a thing
    // away from an empty collection is undefined behaviour (i.e. not
    // explicitly checked).
    void take_one_away();
  private:
    int count_of_things;
    thing const& type_of_thing;
  };
 
  // equal_collection constructor
  equal_collection::equal_collection(int count, thing const& what):
    count_of_things(count),
    type_of_thing(what)
  {
  }
 
  // get singular. The singular of the collection is just the number
  // followed by the thing, proper pluralized. The fact that it's
  // grammatically still a plural form doesn't matter for the problem
  // at hand.
  std::string equal_collection::singular() const
  {
    std::ostringstream oss;
    oss << count_of_things << " ";
    if (count_of_things == 1)
      oss << type_of_thing.singular();
    else
      oss << type_of_thing.plural();
    return oss.str();
  }
 
  // get plural. For collections, the plural is just "times " followed
  // by the singular. That is 3 collections of 4 bottles each give 3
  // times 4 bottles.
  std::string equal_collection::plural() const
  {
    return "times " + singular();
  }
 
  // tell if there are still things to take away. There are things to
  // take away if there are more than 0 things.
  bool equal_collection::there_is_some_left()
  {
    return count_of_things > 0;
  }
 
  // take one thing away from the collection. That is, just decrement
  // the count of things.
  void equal_collection::take_one_away()
  {
    --count_of_things;
  }
 
  // =================================================================
 
  // ************
  // * The beer *
  // ************
 
  class beer: public thing
  {
  public:
    std::string singular() const { return "beer"; }
    std::string plural() const { return "beers"; }
  };
 
  // =================================================================
 
  // **************
  // * The bottle *
  // **************
 
  class bottle: public thing
  {
  public:
    std::string singular() const { return "bottle"; }
    std::string plural() const { return "bottles"; }
  };
 
  // =================================================================
 
  // ************
  // * The wall *
  // ************
 
  class wall: public thing
  {
  public:
    std::string singular() const { return "wall"; }
    std::string plural() const { return "walls"; }
  };
 
  // =================================================================
 
  // this is the class for the song.
  class song
  {
  public:
    song(int bottle_count);
    void sing(std::ostream& where); // note: singing the song modifies it!
  private:
    beer beverage;
    bottle drink_source;
    container bottle_of_beer;
    equal_collection collection_of_bottles;
    wall bottle_storage;
    container wall_of_bottles;
  };
 
  song::song(int bottle_count):
    bottle_of_beer("%self% of %contained%", drink_source, beverage),
    collection_of_bottles(bottle_count, bottle_of_beer),
    wall_of_bottles("%contained% on the %self%",
                    bottle_storage, collection_of_bottles)
  {
  }
 
  void song::sing(std::ostream& where)
  {
    while (collection_of_bottles.there_is_some_left())
    {
      where << wall_of_bottles.singular() << ".\n"
            << collection_of_bottles.singular() << ".\n"
            << "Take one down, pass it around.\n";
      collection_of_bottles.take_one_away();
      where << wall_of_bottles.singular() << ".\n\n";
    }
  }
}
 
int main()
{
  bottle_song::song song(100);
  song.sing(std::cout);
  return 0;
}
qwone
2016-07-17 11:53:34

Это заговор какой-то.Народ в Ардуино тупо забывает о Классах.

Nefreemen
2016-07-13 11:49:34

Ушел курить и пить пиво  big_smile. Или уже написал сам big_smile .

NoName
2016-07-13 10:25:39

а где потерялся ТС?  big_smile

Nefreemen
2016-07-13 10:16:09

Да я рассматривал что то подобное. Согласен что структуры идеальный вариант построения многоуровневых меню. Но к большому моему огорчению они мне не подошли поскольку почти все элементы значений через сериал ( JSON ) шлются в ESP8266 и обратно. Да плюс ко всему этому  разные типы. Лепить что то типа структуры из структур не было времени, да опять тот же JSON, кроме этого не все так просто и однозначно с библиотекой Serial в Arduino (max 256 байт буфер). Собственно я привел пример что происходит если покрутить вправо влево или нажать кнопку. А построение многоуровневых меню это совершенно отдельная  тема. Ее то как раз можно рассматривать отдельно поскольку не важно как происходит выбор (кнопкой или энкодером). При построении меню на базе энкодера есть только один ньюанс, что в меню должен присутствовать пункт выхода (возврата) на предыдущий уровень .

NoName
2016-07-13 09:12:55

"нащадки" не будут Вам благодарны )  я бы не рискнул использовать ваш пример )))))
НО! работает, в нашем деле, это пожалуй, один из важнейших факторов )

я  предпочитаю такое оформление, если предусматривается работа со строкой  ( 4 подменю на экране )
код избыточен, но как обычно через пару лет понимаю что куда  идет

const SMenu_TICxxx xxx[] = {
 ///  STR            E L R EXE L:R ( Local )
// --- pos 00  ----  // 
 { "Manual control       ",1,0,0, 0, 1,1, // переходим на старт
   "Setting              ",2,0,0, SelectLine0, 0,0,
   "X                    ",0,0,0, SelectLine0, 0,0,
   "Y                    ",0,0,0,SelectLine0, 0,0,},
// --- pos 01  ----  // 
{  "max xxxx             ",1,1,1, SelectLine0, 255,255,
   "min xxxx             ",0,0,0, SelectLine0, 0,0,
   "pos                  ",0,0,0, 0, 0,0,
   "% xxx.xx R           ",0,0,0, SelectLine0, 0,0 },
};
Nefreemen
2016-07-13 00:37:23

Фрагменты программы термостата инкубатура. Дисплей 128х64
/*****************************************************
*       21.04.16    13:25                          *
*****************************************************/

#include <ArduinoJson.h>
#include <DS1307.h>
#include <Encoder.h>
#include <DHT.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include <U8glib.h>
#include <EEPROM.h>
#include <avr/wdt.h>

/**************** Macro **********************/

#define ONE_WIRE_BUS       22           // DS18B20
#define DHTPIN             23             
#define DHTTYPE DHT22                   // DHT 22  (AM2302)
#define PIN_VENT1                       // резерв
#define PIN_VENT2                       // резерв
#define PIN_LIGHT          12           // подсветка дисплея
#define READ_ACTUATOR       3           // сенсор актуатора
#define TURN_ACTUATOR      48           // включение актуатра
#define DIRECT_ACTUATOR    46           // направление движения актуатора
#define BOOTOM_ACTUATOR    A2           // кнопка управления актуатором
#define PIN_ENCODER1        2           // энкодер
#define PIN_ENCODER2       24           // энкодер
#define PIN_ENCODER_BOOTOM 25           // кнопка энкодера
#define SENSETIVE_ENC       2           // чувств. энкодера
#define HITER_UP1          11           // нагреватель 1  вверх
#define HITER_UP2          10           // нагреватель 2  вверх
#define HITER_DOWN1        9            // нагреватель 1  низ
#define HITER_DOWN2        8            // нагреватель 2  низ
#define HITER_VENT         A14          // вентилятор нагревателей
#define HITER_WATER        A15          // ТЭН вода 
#define VENT_WATER         A8           // вентилятор вода
#define VENT_BOX           A9           // вентилятор камеры


/********************** Proto *************************/

DHT dht( DHTPIN , DHTTYPE );
OneWire oneWire( ONE_WIRE_BUS );
DallasTemperature sensors(&oneWire);
DeviceAddress thermometer_low; //, thermometer_high;
DeviceAddress thermometer_high;

//U8GLIB_ST7920_128X64_1X u8g(50, 51, 53);  // SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
U8GLIB_ST7920_128X64_4X u8g(50, 51, 53);  // SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17

//U8GLIB_ST7920_128X64_1X u8g(12, 11, 10);  // SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17
//U8GLIB_ST7920_128X64_4X u8g(12, 11, 10);    // SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17

Encoder myEnc(PIN_ENCODER1, PIN_ENCODER2);

//DS1307 rtc(A4, A5);
DS1307 rtc(20, 21);

Time date_time;

/***************** Переменные *************************/

int menu_current = 0;
int menu_level = 0;
int item_current = 0;
int i = 0;
int n = 2;

int rotor  = 0;
int lastHour = 0;
int lastMinute = 0;
int rotorMinute = 0;
int lastrotorHour = 0;

float P, dhtt, dhth, dst, dht_t, dht_h;

long lastTime = 0;
long lastTime_light = 0;

String Items = "";
String Exit = "No Save";
long oldPosition  = 0;

float Value = 0;

String StatusSinhro = "";
String StatusInfo = "";
String HitUp = "";
String HitDown = "";
String HitWat = "";
String Vent = "";
String Actuator = "";
String TimeSinhro = "";
String ConstSinhro = "";
String SendSinhro = "";

boolean getsinhro = false;
boolean constSinhro = false;
// Переменные актуатора
int directActuator = 0;     //false - вниз, true - вверх
//boolean initActuator = false;
//long lastTime_Actuator = 0;
int old_actPosition = 0;
volatile int actPosition = 0;

/******************** Array ********************/

const char *menu_strings[ ] = { "Main", "Termostat", "Amendment", "Info", "Elapsed time", "Network" };
int l = 6;

char* FloatTopic [ ] = { "type", "tmp1", "tmp2", "tmpdht", "hmdr", "tmp3", "rotor", "alarm", "hitUp", "hitDown" };
float FloatValue [ ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int work = 10;

char* ConstTopic [ ] = { "type", "tmp1", "tmp2", "hmdr", "tmp3", "rotor", "dltmp1",
                         "dltmp2", "dltmp3", "dlthmdr", "amt1", "amt2", "amt3"
                       };
float ConstValue [ ] = { 1, 37.81, 37.81, 60, 37.81, 4, 0.06, 0.06, 0.06, 1.0, 0.0, 0.0, 0.0 };
float ConstUp [ ] = { 1, 40.0, 40.0, 90, 40.0, 6, 0.24, 0.24, 0.24, 2.5, 1.0, 1.0, 1.0 };
float ConstDown [ ] = { 1, 35.0, 35.0, 60, 35.0, 0, 0.0, 0.0, 0.0, 0.0, -1.0, -1.0, -1.0 };
float ConstStep [ ] = { 1, 0.01, 0.01, 0.5, 0.01, 1, 0.06, 0.06, 0.06, 0.5, 0.06, 0.06, 0.06 };
int cons = 13;

char* ItemConst [ ] = { "Exit", "TempUp", "TempDown", "Humidity", "TempHiter", "Rotor",
                        "DltTempUp", "DltTempDown", "DltTempHiter", "DltHumidity", "AmdTempUp",
                        "AmdTempDown", "AmdTempHiter"
                      };
int item = 13;

char* InfDtTopic [ ] = { "type", "dt1", "dt2", "dt3", "dt4", "dt5" };
long InfDtValue [ ] = { 3, 30212, 30209, 22810, 21522, 21923 };

char* ItemInf [ ] = {"Exit", "Date" };
int iteminf = 2;

char* InfGoTopic [ ] = { "type", "go1", "go2", "go3", "go4", "go5" };
float InfGoValue [ ] = { 4, 11.8, 13.11, 14.15, 19.20, 20.23 };
int inf = 6;

char* NetTopic [ ] = { "type", "ip", "ssid", "passw", "mqttip" };
String NetValue [ ] = { "ip", "192.168.1.180", "***", "*****", "192.168.1.20" };
int net = 5;

...........................

/**************************************************
*             Энкодер                            *
* ************************************************/

void EncoderRead( void )
{
  if (menu_level == 0) {
    EncoderReadL0();
  }
  if (menu_level == 1) {
    EncoderReadL1();
  }
  if (menu_level == 2) {
    EncoderReadL2();
  }
}

void EncoderReadL0(void)
{
  long newPosition = myEnc.read();
  if (newPosition - oldPosition != 0 ) {
    digitalWrite( PIN_LIGHT, HIGH );   // подсветка дисплея
  }
  if (newPosition - oldPosition  < -2 ) {
    menu_current --;
    if ( menu_current < 0 ) {
      menu_current = l - 1;             //  l - коолл. элиментов
    }
  }
  if (newPosition - oldPosition > 2 ) {
    menu_current ++;
    if ( menu_current > l - 1 ) {
      menu_current = 0;
    }
  }
  oldPosition = newPosition;
}

void EncoderReadL1(void)
{
  long newPosition = myEnc.read();
  if (newPosition - oldPosition != 0 ) {
    digitalWrite( PIN_LIGHT, HIGH );
  }
  if (menu_current == 1) {
    if (newPosition - oldPosition  < -2 ) {
      item_current --;
      if ( item_current < 0 ) {
        item_current = item - 1 - 3;
      }
      if ( item_current == 0 ) {
        Exit = "Save";
      }
    }
    if (newPosition - oldPosition > 2 ) {
      item_current ++;
      if ( item_current > item - 1 - 3 ) {
        item_current = 0;
      }
      if ( item_current == 0 ) {
        Exit = "Save";
      }
    }
  }
  if (menu_current == 2) {
    if (newPosition - oldPosition  < -2 ) {
      item_current --;
      if (( item_current < 10 ) && ( item_current > 0 )) {
        item_current = 0;
      }
      if ( item_current == 0 ) {
        Exit = "Save";
      }
      if ( item_current < 0 ) {
        item_current = item - 1;
      }
    }
    if (newPosition - oldPosition > 2 ) {
      item_current ++;
      if ( item_current > item - 1 ) {
        item_current = 0;
      }
      if ( item_current == 0 ) {
        Exit = "Save";
      }
      if ( (item_current < item - 1 - 3) && (item_current > 0) ) {
        item_current = item - 1 - 2;
      }
    }
  }

  if (menu_current == 3) {
    if (newPosition - oldPosition  < -2 ) {
      if (Items == "Exit") {
        Items = (String) date_time.hour + "h " + (String) date_time.date + "d " +
                (String) date_time.mon + "m ";
        Value = 1;
        item_current = 1;
      }
      else {
        Items = "Exit";
        item_current = 0;
        Exit = "Save";
      }
    }
    if (newPosition - oldPosition > 2 ) {
      if (Items == "Exit") {
        Items = (String) date_time.hour + "h " + (String) date_time.date + "d " +
                (String) date_time.mon + "m ";
        Value = 1;
        item_current = 1;
      }
      else {
        Items = "Exit";
        Exit = "Save";
        item_current = 0;
      }
    }
    oldPosition = newPosition;
  }
  if ((menu_current == 1) || (menu_current == 2)) {
    Items = (String)ItemConst [ item_current ];
    Value = ConstValue [ item_current ];
    oldPosition = newPosition;
  }
}

void EncoderReadL2(void)
{
  long newPosition = myEnc.read();
  if (newPosition - oldPosition != 0 ) {
    digitalWrite( PIN_LIGHT, HIGH );
  }
  if (( menu_current == 1 ) || ( menu_current == 2 )) {
    if ( item_current != 0 ) {
      if (newPosition - oldPosition  < -2 ) {
        ConstValue [ item_current ] = ConstValue [ item_current ] - ConstStep [ item_current ];
        if ( ConstValue [ item_current ] < ConstDown [ item_current ] ) {
          ConstValue [ item_current ] = ConstUp [ item_current ];
        }
        Value = ConstValue [ item_current ];
      }
      if (newPosition - oldPosition > 2 ) {
        ConstValue [ item_current ] = ConstValue [ item_current ] + ConstStep [ item_current ];
        if ( ConstValue [ item_current ] > ConstUp [ item_current ] ) {
          ConstValue [ item_current ] = ConstDown [ item_current ];
        }
        Value = ConstValue [ item_current ];
      }
    }
    if ( item_current == 0 ) {
      if (newPosition - oldPosition  < -2 ) {
        if ( Exit == "Save" ) {
          Exit = "No Save";
        }
        else {
          Exit = "Save";
        }
      }
      if (newPosition - oldPosition > 2 ) {
        if ( Exit == "Save" ) {
          Exit = "No Save";
        }
        else {
          Exit = "Save";
        }
      }
    }
    oldPosition = newPosition;
  }
  if (menu_current == 3) {
    if ( item_current == 1) {
      if (newPosition - oldPosition  < -2 ) {
        Value--;
        if (Value < 1) {
          Value = inf - 1;
        }
      }
      if (newPosition - oldPosition > 2 ) {
        Value++;
        if ( Value > inf - 1) {
          Value = 0;
        }
      }
    }
    if ( item_current == 0 ) {
      if (newPosition - oldPosition  < -2 ) {
        if ( Exit == "Save" ) {
          Exit = "No Save";
        }
        else {
          Exit = "Save";
        }
      }
      if (newPosition - oldPosition > 2 ) {
        if ( Exit == "Save" ) {
          Exit = "No Save";
        }
        else {
          Exit = "Save";
        }
      }
    }
    oldPosition = newPosition;
  }
}

void EncoderBootom(void)
{
  if (menu_level == 0) {
    if (( menu_current == 1 ) || ( menu_current == 2 )) {
      delay(20);
      Items = (String)ItemConst [ item_current ];
      Value = ConstValue [ item_current ];
      menu_level = 1;
      return;
    }
    if ( menu_current == 3 ) {
      delay(20);
      Items = "Exit";
      Exit = "Save";
      menu_level = 1;
      return;
    }
  }

  if (menu_level == 1) {
    if (( menu_current == 1 ) || ( menu_current == 2 )) {
      delay(20);
      Items = (String)ItemConst [ item_current ];
      Value = ConstValue [ item_current ];
      menu_level = 2;
      return;
    }
    if (menu_current == 3) {
      menu_level = 2;
      return;
    }
  }

  if (menu_level == 2) {
    if (( menu_current == 1 ) || ( menu_current == 2 )) {
      if (item_current != 0) {
        delay(20);
        Items = (String)ItemConst [ item_current ];
        Value = ConstValue [ item_current ];
        menu_level = 1;
      }
      if (item_current == 0) {
        if (Exit == "Save") {
          JsonSerial(1);
          SaveValue1EEPROM();
          menu_level = 0;
          return;
        }
        else {
          ReadValue2EEPROM();
          JsonSerial(1);
          menu_level = 0;
        }
      }
      return;
    }
    if (menu_current == 3) {
      if ((item_current == 0) && ( Exit == "Save")) {
        //Написать сохранение
        InfDtValue [ (int)Value ] = date_time.mon * 10000L + date_time.date * 100L + date_time.hour;
        GoInf();
        SaveValue2EEPROM();
        menu_level = 0;
        JsonSerial(3);
        //delay(1000);
        JsonSerial(4);
        return;
      }
      if ((item_current == 0) && ( Exit == "No Save")) {
        menu_level = 0;
        return;
      }
      if (item_current == 1) {
        menu_level = 1;
      }
    }
  }
}
Писалось все в "лоб" переписывалось фиг знает сколько раз поэтому ни о какой оптимизации речи не может быть. Комментариев тоже нет  sad .

NoName
2016-07-12 17:46:26

Nefreemen, мне интересно как сделали меню для "сакральных" трех кнопок )

Nefreemen
2016-07-12 17:00:26

Могу привести фрагмент кода своего меню (3 уровня) для энкодера если интересно.

vvr
2016-07-11 22:09:24
electronhic пише:

Помогите сделать многоуровневое меню на енкодере.

это коммерческое предложение или просто так для вас поработать)))

NoName
2016-07-11 17:40:10

привет,
RDA5807M освоили?  )

подскажите пожалуйста какой индикатор Вы используете.

electronhic
2016-07-11 15:25:56

Помогите сделать многоуровневое меню на енкодере.

Підвал форуму