群组信息 私有

administrators

  • Lesson 13.1. UI. Full manual

    The purpose of this lesson

    Hi! Today we will get acquainted with such a tempting thing as the M5 UI. This is a library designed to create a user interface. Thanks to M5 UI you can connect all kinds of fields, buttons, sliders and switches with a couple of lines of code, create conditional layers. Although the process of connecting UI elements is very simple, you can also use the visual M5 UI Designer for Arduino IDE tool.

    Figure 1

    It is necessary to consider all the existing elements of the library M5 UI in practice, as well as get acquainted with the process of creating the interface in the application M5 UI Designer.

    Short help

    A graphical interface is a set of functional elements that are required for interaction with the user. As these elements appear in various fields of the input/output of text, buttons, checkboxes, sliders, radio buttons and many others. As an example of a graphical interface, let's look at figure 2.

    Figure 2. User interface element

    In order to set the focus to the next element (the select element) use alternate pressing the Fn and TAB

    Inputbox represents the input area of the text information on the screen with a fixed height of 50 px. The width can be set by the user, but cannot be less than 32 px. At the top is the inscription (for example: Enter user name), note that at the end will automatically be added the symbol ':'. At the bottom is a rectangular area in which the user can enter data from the keyboard. When you focus on this element-the bottom of the backlight. To change the value, use the letters and numbers keys on the keyboard.

    Textbox is an area where text information is displayed on the screen. Dimensions can be user-defined, but cannot be smaller than the size of a single character. This element consists of one part. The text fits over the entire area and does not go beyond. There is no focus on this element.

    Waitingbar is an area for displaying graphical information on a screen with a fixed height of 50 px. The width can be set by the user, but cannot be less than 12 px. At the top is the inscription (for example: Connection to Wi-Fi), note that at the end will automatically be added the symbol ':'. At the bottom is a rectangular area, which is painted periodically orange and black squares. There is no focus on this element.

    Progressbar is an area for displaying graphical information on a screen with a fixed height of 50 px. The width can be set by the user, but cannot be less than 12 px. At the top is the inscription (for example: Times of the check), note that at the end will automatically be added the symbol ':'. In the lower part is a rectangular area that is colored according to the value specified (10% red, 30% orange, 80% green and 100% blue color). There is no focus on this element.

    Selectbox represents the text information selection area on the screen with a fixed height of 50 px. The width can be set by the user, but cannot be less than 44 px. At the top is the inscription (for example: Mode), note that at the end will automatically be added the symbol ':'. At the bottom is a rectangular selection area where the user can select data from the keyboard. To change the value, press the Fn key, then K / M or similar up / down arrows.

    Checkbox represents the input area of a single value (true/false) on a screen with a fixed height of 32 px. The width can be set by the user, but cannot be less than 44 px. On the left side there is a flag (if it is colored, true, if not - false). On the right side is the inscription (for example: Remember password). To remove or set the flag, press the SPACE key.

    Button represents the call area of any user-defined function (with a void signature (String*)) with a fixed height of 32 px. The width can be set by the user, but cannot be less than 22 px. In the center is the inscription (for example: Launch). A distinctive feature of this element is the support of icons from the standard set (Fig. 3). To press the button, press the SPACE key.

    Figure 3. Standard icon codes 24 x 24 px

    If the icon is connected, the minimum width will be 51 px.

    Rangebox represents the selection of an integer value from a given range with a fixed height of 50 px. The width can be set by the user, but cannot be less than 32 px. At the top is the inscription (for example: Speed), note that at the end will automatically be added the symbol ':'. At the bottom is the area containing the strip and the adjacent slider. To change the value, press the Fn key, then N / $ or similar left / right arrows.

    List of components for the lesson:

    • PC/MAC;
    • M5STACK;
    • FACES;
    • FACES Keyboard;
      -USB-C cable from standard set;
    • colored wires from the standard set (type socket-plug);
    • prototype Board for soldering 5 x 7 cm;
    • soldering iron 40 or 60 W;
    • rosin soldering;
    • tin soldering;
    • scissors;
    • resistor 36 ohms (1 PC.);
    • 160K resistor (1 PC .);
    • chip 74HC595N (1 PC .);
    • resistor 220 Ohm (1 PC.);
    • LEDs: orange, green, yellow, red (4 PCs.);
    • powerful transistor BC337 (1 PC.);
    • resistor 100 kOhm (1 PC.);
    • DC motor (1 PC.).

    Let's start!

    Step 1. Install the M5 UI library

    Follow the link M5 UI for Arduino IDE in the section Downloads(at the bottom of this page) and download the archive with the library from GitHub (Fig. 3.1).

    Figure 3.1. Click the Clone or download button, Then download ZIP

    Run the Arduino IDE and add the downloaded archive (Fig. 3.2).

    Figure 3.2. Click Sketch, Include Library, Add .ZIP Library...

    After that, the library will be successfully added. That's all.

    Step 2. Installation and tools of M5 UI Designer

    Similarly, click the M5 UI Designer for Arduino IDE link in the Downloads section (at the bottom of this page) and download the library archive from GitHub to your desktop, then extract the content and open the index document.html using a browser (beta-version works only under browsers on Chrome engine) (Fig. 3.4)

    Figure 3.4

    This completes the installation of the tool (Fig. 3.5).

    Figure 3.5. M5 UI Designer

    Step 3. Enter key-special (⊙_⊙)

    Imagine this situation-the user has entered the necessary information in the same Inputbox and he needs to process it, for example: send somewhere. How do I tell M5 that the user has completed input? That's right-press Enter (as one of the options).
    Anywhere in the code, you can always bind a user-defined function to the Enter key, as long as the signature of the user - defined function is as follows void (String*).

    void userFunction1(String* rootVar) {
    	// reaction after pressing the Enter key
    }
    
    ...
    UIEnter = userFunction1;
    

    Step 4. Morse code, Inputbox and Textbox (^_^♪)

    Let's add our first element-Inputbox. In it we will enter the text and after pressing the Enter key will hear from the speaker Morse code (Fig. 4).

    Figure 4. Morse code

    Open M5 UI Designer, drag and drop Inputbox and Textbox, set width and headers. In Tools > User Functions, click the yellow lightning icon and enter the name of the new Morse user function. Then, in the Properties > Enter key section, select Morse (Fig. 4.1).

    Figure 4.1.

    Select all the text from the Source section and copy it to the Arduino IDE.

    /* User functions: */
    void Morse(String* rootVar) {
     int MorseCodes[] =
     {
      0,1,-1,-1, // A
      1,0,0,0, // B
      1,0,1,0, // C
      1,0,0,-1, // D
      0,-1,-1,-1, // E
      0,0,1,0,  //F
      1,1,0,-1, // G
      0,0,0,0,  // H
      0,0,-1,-1,  // I
      0,1,1,1, // J
      1,0,1,-1, // K
      0,1,0,0, // L
      1,1,-1,-1, // M
      1,0,-1,-1,  // N
      1,1,1,-1, // O
      0,1,1,0,  // P
      1,1,0,1,  // Q
      0,1,0,-1, // R
      0,0,0,-1, // S
      1,-1,-1,-1, // T
      0,0,1,-1, // U
      0,0,0,1,  // V
      0,1,1,-1, // W
      1,0,0,1,  // X
      1,0,1,1, // Y
      1,1,0,0 // Z
     };
     for (int i = 0; i < UIInputbox_v05700a.length(); i++) {
      char chr = UIInputbox_v05700a[i];
      if (chr == ' ')
      {
        M5.Speaker.mute();
        delay(350);
      }
      else
      {
        int chrNum = (chr - 'a') * 4;
        for (int j = chrNum; j < (chrNum + 4); j++)
        {
          M5.Speaker.tone(440);
          if (MorseCodes[j] == 0)
            delay(50);
          else if (MorseCodes[j] == 1)
            delay(200);
          M5.Speaker.mute();
          delay(150);
        }
      }
     }
    }
    

    As you can see - the entire code framework generated by M5 UI Designer remained absolutely unchanged in the standard form. The only thing we have changed is the custom Morse function. It's very simple :) (Fig. 4.2).

    Figure 4.2

    Step 5. Bruteforce and Waitingbar ≧ ( ◕ ‿ ‿ ◕ ) ≦

    Similarly, we add Waitingbar. We will generate an 8-bit random code and then select it. The progress bar will just Waitingbar. Once the code is matched Waitingbar will be hidden. The process will start after pressing the Enter key (Fig. 5).

    Figure 5.

    In this example, we modify the default layer function by adding void UIDiable(bool, String*) after enumerating the elements. This is to ensure that the Waitingbar is hidden for the duration of the inactivity.

    /* Function for layer default: */
    void LayerFunction_default(String* rootVar) {
     /* UI Elements */
     ...
     UIDisable(true, &UIWaitingbar_yksk2w8);
    }
    

    void UIDisable(bool, String*) or void UISet (String*, int) used to hide an element. Where bool - can be set to true/false i.e. hide/show element; String* - pointer to rootVar (root variable) element.

    Now add the contents of the void Brutforce(String) function*):

    /* User functions: */
    void Brutforce(String* rootVar) {
      /* make random original key */
      uint8_t okey = random(0, 256); 
      String okeyString = "";
      for (int i = 0; i < 8; i++) {
        okeyString += String((okey >> i) & 1);
      }
      UISet(&UITextbox_sxjzx0g, okeyString); // set value for Textbox
      
      UIDisable(false, &UIWaitingbar_yksk2w8); // show the Waitingbar
    
      uint8_t key;
      
      while (true) {
        key++;
        String keyString = String();
        for (int i = 0; i < 8; i++) {
          keyString += String((key >> i) & 1);
        }
        UISet(&UITextbox_eyar2x, keyString);
        Serial.print(key);
        Serial.print(" ");
        Serial.println(okey);
        if (key == okey) break;
        M5.Speaker.tone(800);
        delay(40);
        M5.Speaker.mute();
      }
      UIDisable(true, &UIWaitingbar_yksk2w8);
      M5.Speaker.tone(600);
      delay(75);
      M5.Speaker.mute();
      M5.Speaker.tone(800);
      delay(75);
      M5.Speaker.mute();
      M5.Speaker.tone(500);
      delay(75);
      M5.Speaker.mute();
    }
    

    To set the value for an element, use the void UISet(String*, String) or void UISet(String*, int) function. Where String* is a pointer to the rootVar (root variable) of the element;String or int is the new value.

    Now run and see what happened (Fig. 5.1).

    Figure 5.1

    Step 6. BatteryCheck and Progressbar Σ(O_O)

    Let's make a tester charge conventional finger batteries type A, AA, AAA. Indication will be carried out using the Progressbar in percentage terms, and in addition at the bottom using Textbox will display the voltage in mV (Fig. 6).

    Figure 6.

    Here we modify the layer function

    /* Function for layer default: */
    void LayerFunction_default(String* rootVar) {
     /* To open this layer use: */
     ...
     // BattaryCheck
     while (true) {
      int voltage = analogRead(35) * 3400 / 4096;
      int percentage = voltage * 100 / 1600;
      UISet(&UIProgressbar_1mlmhcu, percentage);
      UISet(&UITextbox_gtaetjh, voltage);
      delay(500);
     }
    }
    

    Constantly, every 500 MS, in the cycle we will take readings from the ADC port 0 (pin 35).
    Then we will calculate the voltage: 3400 mV is the reference voltage, 4096 is the resolution of the ADC. The switching circuit is shown in figure 6.1.

    Note-M5 Bottom is used instead of FACES

    Figure 6.1. Visual scheme of switching on the built-in ADC to the finger battery

    The device works great! Now you have a great tool to check the batteries (Fig. 6.2).

    Figure 6.2

    Step 7. LEDshift and Selectbox ( ◡ ‿ ◡ *)

    Take four LEDs (orange, green, red and yellow), connect them through the shift register 74HC595N to M5 according to the scheme in figure 7.

    Figure 7. Wiring the LEDs to the M5 via the shift register

    Create a graphical interface using M5 UI Designer, as in the previous examples, and copy the code (Fig. 7.1).

    Figure 7.1.

    Now let's modify the code.

    Add the pin numbers on the M5 for connecting the shift register 74HC595N after RootVar's:

    /* RootVar's for UI elements (note: not edit manually) */
    ...
    // Shift register pinout
    int SH_CP = 17;
    int ST_CP = 2;
    int DS = 5;
    

    Next, we add the contents of the void SelectColor(String) function*):

    /* User functions: */
    void SelectColor(String* rootVar) {
      int led = UIOptionValue(&UISelectbox_6foo6h).toInt();
      digitalWrite(ST_CP, LOW);
      shiftOut(DS, SH_CP, MSBFIRST, led);
      digitalWrite(ST_CP, HIGH);
      delay(100);
    }
    

    In order to get selected option from Selectbox using function String UIOptionValue(String*).

    Now you need to fill the Selectbox with options. to do this, we add 5 lines of code to the very beginning of the layer function:

    /* Function for layer default: */
    void LayerFunction_default(String* rootVar) {
     // add options to Selectbox
     UIOption("OFF", "0", &UISelectbox_6foo6h);
     UIOption("RED", "17", &UISelectbox_6foo6h);
     UIOption("YELLOW", "3", &UISelectbox_6foo6h);
     UIOption("GREEN", "5", &UISelectbox_6foo6h);
     UIOption("ORANGE", "9", &UISelectbox_6foo6h);
     ...
    }
    

    To add an option to the Selectbox, use the void UIOption(String, String, String*) function. Where the first String is the signature of the option that the user sees; the second String is the value of the option that is hidden from the user; String* is a pointer to the rootVar (root variable) of the element

    At the end, add three lines after the comment below. Thus, we will set up the M5 contacts to output:

    void setup() {
     ...
     /* Prepare user's I/O. For example pinMode(5, OUTPUT); */
     pinMode(SH_CP, OUTPUT);
     pinMode(ST_CP, OUTPUT);
     pinMode(DS, OUTPUT);
     ...
    }
    

    That's it! :) (fig. 7.2).

    Figure 7.2

    Step 8. SmartDrill and team from Rangebox, Checkbox, Button (。• ᵕ •。`)

    What can combine Rangebox, Checkbox and Button? Correct! - drilling machine. Take a DC motor (for example, from the cassette player), transistor (to the power came), resistor to block the current base, a few wires, breadboard and collect! Sometimes it is necessary to make several holes one by one, and sometimes it is necessary to make only one, so there is an idea to allocate some time to the drill, and then turn it off automatically: here we come to the aid of the Checkbox.

    Figure 8

    With Rangebox we will adjust the supply voltage on the motor. The button will start and stop the process (Fig. 8). Please note-the button with the icon ;)

    The Enter button here is not useful to us, so Enter key for all elements will be empty (zero).
    Instead, we will call the custom Drill function using The callback property for the button.

    What's code? After Rootvar's add bool startStatus, which will allow the program to understand whether the engine is running or not.

    /* RootVar's for UI elements (note: not edit manually) */
    ...
    // User's variables
    bool startStatus = false;
    

    Fill the user-defined function void Drill(String*):

    void Drill(String* rootVar) {
      startStatus = (startStatus) ? false : true;
      if (startStatus)
      {
        int power = UIRangebox_ztj619h.toInt() * 255 / 100;
        dac_out_voltage(DAC_CHANNEL_1, power);
        if (UICheckbox_1n9gs0b == "true")
        {
          UICaption("WAIT", &UIButton_enhu9fc);
          delay(25000);
          Drill(0);
          return;  
        }
        UICaption("STOP", &UIButton_enhu9fc);
      }
      else
      {
        dac_out_voltage(DAC_CHANNEL_1, 0);
        UICaption("START", &UIButton_enhu9fc);
      }
    }
    

    To set the value on the analog port, use the function dac_out_voltage (DAC_CHANNEL_1, int). Where DAC_CHANNEL_1 - channel number (pin 25), int - value.

    ;

    In order to change the title of any of the UI elements use the function UICaption(String, String)*. Where String - new header; String* - pointer to rootVar (root variable) of the element

    Hurray! Now you can try drilling (Fig. 8.1).

    Figure 8.1

    Step 9. Launch!

    In the section "Downloads" attached video demonstration. This completes the lesson.

    Downloads

    发布在 NEWS & LESSONS
  • RE: Doesn't work sample sketch "MP9250BasicAHRS" on M5Stack Gray

    The latest arduino-esp32 I2C have a problem, I checkout out to the e63aa4065092c9a3a0547b2649a509585866ce87 can fix the problem.

    cd ~/Documents/Arduino/hardware/espressif/esp32
    git checkout e63aa4065092c9a3a0547b2649a509585866ce87
    
    发布在 FAQS
  • Урок 13.1. ВСЁ-ВСЁ ОБ M5 UI

    Цель урока

    Привет! Сегодня мы познакомимся с такой заманчивой штукой как M5 UI. Это библиотека предназначенная для создания пользовательского интерфейса. Благодаря M5 UI Вы можете с помощью пары строк кода подключать всевозможные поля, кнопки, ползунки и переключатели, создавать условные слоя. Несмотря на то, что процесс подключения элементов UI очень прост, Вы также можете воспользоваться наглядным инструментом M5 UI Designer for Arduino IDE.

    Рисунок 1

    Необходимо рассмотреть все существующие на сегодняшний день элементы из библиоткеки M5 UI на практике, так же ознакомиться с процессом создания интерфейса в приложении M5 UI Designer.

    Краткая справка

    Графический интерфейс представляет собой совокупность функциональных элементов, необходимых для взаимодействия с пользователем. В качестве таких элементов выступают всевозможные поля ввода/вывода текста, кнопки, чекбоксы, ползунки, переключатели и многие другие. В качестве примера графического интерфейса давайте посмотрим на рисунок 2.

    Рисунок 2. Элементы пользовательского интерфейса

    Для того, чтобы установить фокус на следующий элемент (выбрать элемент) используйте поочерёдное нажатие клавиш Fn и TAB

    Inputbox представляет собой область ввода текстовой информации на экране с фиксированной высотой 50 px. Ширина может быть задана пользователем, но не может быть меньше 32 px. В верхней части располагается надпись (например: Enter user name), обратите внимание на то, что в конце автоматически будет добавлен символ ':'. В нижней части располагается прямоугольная область, в которую пользователь может вводить данные с клавиатуры. При наведении фокуса на данный элемент - происходит подсветка нижней части. Для того чтобы изменить значение используйте клавиши с буквами и цифрами на клавиатуре.

    Textbox представляет собой область вывода текстовой информации на экране. Размеры могут быть заданы пользователем, но не могут быть меньше размеров одного символа. Состоит данный элемент из одной части. Текст умещается по всей площади и не выходит за пределы. Наведение фокуса на данный элемент не предусмотрено.

    Waitingbar представляет собой область вывода графической информации на экране с фиксированной высотой 50 px. Ширина может быть задана пользователем, но не может быть меньше 12 px. В верхней части располагается надпись (например: Connection to Wi-Fi), обратите внимание на то, что в конце автоматически будет добавлен символ ':'. В нижней части располагается прямоугольная область, которая закрашивается периодически оранжевыми и черными квадратами. Наведение фокуса на данный элемент не предусмотрено.

    Progressbar представляет собой область вывода графической информации на экране с фиксированной высотой 50 px. Ширина может быть задана пользователем, но не может быть меньше 12 px. В верхней части располагается надпись (например: Times of the check), обратите внимание на то, что в конце автоматически будет добавлен символ ':'. В нижней части располагается прямоугольная область, которая закрашивается в зависимости установленного значения (до 10% - красным, до 30% - оранжевым, до 80% - зелёным, до 100% - синим цветом). Наведение фокуса на данный элемент не предусмотрено.

    Selectbox представляет собой область выбора текстовой информации на экране с фиксированной высотой 50 px. Ширина может быть задана пользователем, но не может быть меньше 44 px. В верхней части располагается надпись (например: Mode), обратите внимание на то, что в конце автоматически будет добавлен символ ':'. В нижней части располагается прямоугольная область выбора, в которой пользователь может выбирать данные с клавиатуры. Для того чтобы изменить значение нажмите клавишу Fn, затем K / M или аналогично стрелки вверх / вниз.

    Checkbox представляет собой область ввода единственного значения (true/false) на экране с фиксированной высотой 32 px. Ширина может быть задана пользователем, но не может быть меньше 44 px. В левой части расположен флаг (если закрашен, то true, если нет - false). В правой части располагается надпись (например: Remember password). Для того чтобы снять или установить флаг нажмите клавишу SPACE.

    Button представляет собой область вызова любой пользовательской функции (с сигнатурой void (String*)) с фиксированной высотой 32 px. Ширина может быть задана пользователем, но не может быть меньше 22 px. По центру располагается надпись (например: Launch). Отличительной особенностью данного элемента является поддержка иконок из стандартного набора (рис. 3). Для того чтобы нажать на кнопку нажмите клавишу SPACE.

    Рисунок 3. Коды стандартных иконок 24 x 24 px

    Если будет подключена иконка, то минимальная ширина будет 51 px.

    Rangebox представляет собой выбора целого числового значения из заданного диапазона с фиксированной высотой 50 px. Ширина может быть задана пользователем, но не может быть меньше 32 px. В верхней части располагается надпись (например: Speed), обратите внимание на то, что в конце автоматически будет добавлен символ ':'. В нижней части располагается область содержащая полосу и прилегающий ползунок. Для того чтобы изменить значение нажмите клавишу Fn, затем N / $ или аналогично стрелки влево / вправо.

    Перечень компонентов для урока

    • PC/MAC;
    • M5STACK;
    • FACES;
    • FACES Keyboard;
    • кабель USB-C из стандартного набора;
    • цветные провода из стандартного набора (тип розетка-вилка);
    • макетная плата для пайки 5 х 7 см;
    • паяльник 40 или 60 Вт;
    • канифоль паяльная;
    • олово паяльное;
    • ножницы;
    • резистор 36 ом (1 шт.);
    • резистор 160 кОм (1 шт.);
    • микросхема 74HC595N (1 шт.);
    • резистор 220 Ом (1 шт.);
    • светодиоды: оранжевый, зеленый, жёлтый, красный (4 шт.);
    • транзистор мощный BC337 (1 шт.);
    • резистор 100 кОм (1 шт.);
    • электродвигатель постоянного тока (1 шт.).

    Начнём!

    Шаг 1. Установка библиотеки M5 UI

    Перейдите по ссылке M5 UI for Arduino IDE в разделе Downloads (внизу этой страницы) и скачайте архив с библиотекой с GitHub (рис. 3.1).

    Рисунок 3.1. Нажмите на кнопку Clone or download, затем Download ZIP

    Запустите Arduino IDE и добавьте скаченный архив (рис. 3.2).

    Рисунок 3.2. Нажмите Sketch, Include Library, Add .ZIP Library...

    После этого библиотека будет успешно добавлена. На этом всё.

    Шаг 2. Установка и инструмента M5 UI Designer

    Аналогичным образом перейдите по ссылке M5 UI Designer for Arduino IDE в разделе Downloads (внизу этой страницы) и скачайте архив с библиотекой с GitHub в рабочий стол, затем извлеките содержимое и откройте документ index.html с помощью браузера (beta-версия работает исключительно под браузерами на движке Chrome) (рис. 3.4)

    Рисунок 3.4

    На этом установка инструмента завершена (рис. 3.5).

    Рисунок 3.5. Знакомьтесь - M5 UI Designer

    Шаг 3. Клавиша Enter - особенная (⊙_⊙)

    Представьте себе такую ситуацию - пользователь ввёл необходимую информацию в тот же Inputbox и ему необходимо её обработать, например: отправить куда-нибудь. Как сообщить M5 что пользователь завершил ввод? Верно - нажатием на клавишу Enter (как один из вариантов).
    В любом месте кода Вы всегда можете привязать пользовательскую функцию к клавише Enter, главное - чтобы сигнатура пользовательской функции была следующей void (String*).

    void userFunction1(String* rootVar) {
    	// reaction after pressing the Enter key
    }
    
    ...
    UIEnter = userFunction1;
    

    Шаг 4. Азбука морзе, Inputbox и Textbox (^_^♪)

    Давайте добавим первый наш элемент - Inputbox. В него мы будем вводить текст и после нажатия на клавишу Enter будем слышать из динамика код Морзе (рис. 4).

    Рисунок 4. Код Морзе

    Откройте M5 UI Designer, перетащите Inputbox и Textbox, задайте ширину и заголовокти. В разделе Tools > User Functions нажмите на значок "жёлтая молния" и введите имя новой пользовательской функции Morse. Затем в разделе Properties > Enter key выберите Morse (рис. 4.1).

    Рисунок 4.1.

    Выделите весь текст из раздела Source и скопируйте в Arduino IDE.

    /* User functions: */
    void Morse(String* rootVar) {
     int MorseCodes[] =
     {
      0,1,-1,-1, // A
      1,0,0,0, // B
      1,0,1,0, // C
      1,0,0,-1, // D
      0,-1,-1,-1, // E
      0,0,1,0,  //F
      1,1,0,-1, // G
      0,0,0,0,  // H
      0,0,-1,-1,  // I
      0,1,1,1, // J
      1,0,1,-1, // K
      0,1,0,0, // L
      1,1,-1,-1, // M
      1,0,-1,-1,  // N
      1,1,1,-1, // O
      0,1,1,0,  // P
      1,1,0,1,  // Q
      0,1,0,-1, // R
      0,0,0,-1, // S
      1,-1,-1,-1, // T
      0,0,1,-1, // U
      0,0,0,1,  // V
      0,1,1,-1, // W
      1,0,0,1,  // X
      1,0,1,1, // Y
      1,1,0,0 // Z
     };
     for (int i = 0; i < UIInputbox_v05700a.length(); i++) {
      char chr = UIInputbox_v05700a[i];
      if (chr == ' ')
      {
        M5.Speaker.mute();
        delay(350);
      }
      else
      {
        int chrNum = (chr - 'a') * 4;
        for (int j = chrNum; j < (chrNum + 4); j++)
        {
          M5.Speaker.tone(440);
          if (MorseCodes[j] == 0)
            delay(50);
          else if (MorseCodes[j] == 1)
            delay(200);
          M5.Speaker.mute();
          delay(150);
        }
      }
     }
    }
    

    Как видите - весь каркас кода сгенерированный M5 UI Designer остался абсолютно в стандартном виде без изменений. Единственное, что мы изменили - пользовательская функция Morse. Всё очень просто :) (рис. 4.2).

    Рисунок 4.2

    Шаг 5. Bruteforce и Waitingbar ≧(◕ ‿‿ ◕)≦

    Аналогичным образом добавим Waitingbar. Будем генерировать 8-битный случайный код, а затем его подбирать. Индикатором процесса будет как раз Waitingbar. После того, как код будет подобран Waitingbar будет скрыт. Запуск процесса будет происходить после нажатия на клавишу Enter (рис. 5).

    Рисунок 5.

    В этом примере мы несколько модифицируем функцию слоя default добавлением void UIDiable(bool, String*) после перечисления элементов. Это необходимо для того, чтобы Waitingbar был скрыт на время бездействия.

    /* Function for layer default: */
    void LayerFunction_default(String* rootVar) {
     /* UI Elements */
     ...
     UIDisable(true, &UIWaitingbar_yksk2w8);
    }
    

    void UIDisable(bool, String*) или void UISet(String*, int) используется для того, чтобы скрыть элемент. Где bool - может принимать значения true/false т.е. скрыть/показать элемент; String* - указатель на rootVar (корневая переменная) элемента.

    Теперь добавим содержимое функции void Brutforce(String*):

    /* User functions: */
    void Brutforce(String* rootVar) {
      /* make random original key */
      uint8_t okey = random(0, 256); 
      String okeyString = "";
      for (int i = 0; i < 8; i++) {
        okeyString += String((okey >> i) & 1);
      }
      UISet(&UITextbox_sxjzx0g, okeyString); // set value for Textbox
      
      UIDisable(false, &UIWaitingbar_yksk2w8); // show the Waitingbar
    
      uint8_t key;
      
      while (true) {
        key++;
        String keyString = String();
        for (int i = 0; i < 8; i++) {
          keyString += String((key >> i) & 1);
        }
        UISet(&UITextbox_eyar2x, keyString);
        Serial.print(key);
        Serial.print(" ");
        Serial.println(okey);
        if (key == okey) break;
        M5.Speaker.tone(800);
        delay(40);
        M5.Speaker.mute();
      }
      UIDisable(true, &UIWaitingbar_yksk2w8);
      M5.Speaker.tone(600);
      delay(75);
      M5.Speaker.mute();
      M5.Speaker.tone(800);
      delay(75);
      M5.Speaker.mute();
      M5.Speaker.tone(500);
      delay(75);
      M5.Speaker.mute();
    }
    

    Для того, чтобы установить значение для элемента используют функцию void UISet(String*, String) или void UISet(String*, int). Где String* - указатель на rootVar (корневая переменная) элемента; String или int - новое значение.

    Теперь запустим и посмотрим, что получилось (рис. 5.1).

    Рисунок 5.1

    Шаг 6. BatteryCheck и Progressbar Σ(O_O)

    Давайте сделаем тестер заряда обычных пальчиковых батареек типа A, AA, AAA. Индикацию будем осуществлять с помощью Progressbar в процентном соотношении, а в дополнении внизу с помощью Textbox будем отображать напряжение в мВ (рис. 6).

    Рисунок 6.

    Здесь мы модифицируем функцию слоя

    /* Function for layer default: */
    void LayerFunction_default(String* rootVar) {
     /* To open this layer use: */
     ...
     // BattaryCheck
     while (true) {
      int voltage = analogRead(35) * 3400 / 4096;
      int percentage = voltage * 100 / 1600;
      UISet(&UIProgressbar_1mlmhcu, percentage);
      UISet(&UITextbox_gtaetjh, voltage);
      delay(500);
     }
    }
    

    Постоянно, каждые 500 мс, в цикле будем снимать показания с АЦП порт 0 (контакт 35).
    Затем будем рассчитывать напряжение: 3400 мВ - это опорное напряжение, 4096 - разрешающая способность АЦП. Схема включения приведена на рисунке 6.1.

    Обратите внимание - используется M5 Bottom вместо FACES

    Рисунок 6.1. Наглядная схема включения встроенного АЦП к пальчиковой батарейке

    Устройство работает здорово! Теперь у Вас есть отличный инструмент для проверки батареек (рис. 6.2).

    Рисунок 6.2

    Шаг 7. LEDshift и Selectbox ( ◡‿◡ *)

    Возьмем четыре светодиода (оранжевый, зелёный, красный и жёлтый) подключим их через сдвиговый регистр 74HC595N к M5 по схеме на рисунке 7.

    Рисунок 7. Схема подключения светодиодов к M5 с помощью сдвигового регистра

    Создадим графический интерфейс с помощью M5 UI Designer, как в предыдущих примерах, и скопируем код (рис. 7.1).

    Рисунок 7.1.

    Теперь модифицируем код.

    Добавим номера контактов на M5 для подключения сдвигового регистра 74HC595N после RootVar's:

    /* RootVar's for UI elements (note: not edit manually) */
    ...
    // Shift register pinout
    int SH_CP = 17;
    int ST_CP = 2;
    int DS = 5;
    

    Далее добавим содержимое функции void SelectColor(String*):

    /* User functions: */
    void SelectColor(String* rootVar) {
      int led = UIOptionValue(&UISelectbox_6foo6h).toInt();
      digitalWrite(ST_CP, LOW);
      shiftOut(DS, SH_CP, MSBFIRST, led);
      digitalWrite(ST_CP, HIGH);
      delay(100);
    }
    

    Для того, чтобы получить значение выбранной опции из Selectbox используют функцию String UIOptionValue(String*).

    Теперь необходимо наполнить Selectbox опциями. для этого добавим в самое начало функции слоя 5 строк кода:

    /* Function for layer default: */
    void LayerFunction_default(String* rootVar) {
     // add options to Selectbox
     UIOption("OFF", "0", &UISelectbox_6foo6h);
     UIOption("RED", "17", &UISelectbox_6foo6h);
     UIOption("YELLOW", "3", &UISelectbox_6foo6h);
     UIOption("GREEN", "5", &UISelectbox_6foo6h);
     UIOption("ORANGE", "9", &UISelectbox_6foo6h);
     ...
    }
    

    Для того, чтобы добавить опцию в Selectbox используют функцию void UIOption(String, String, String*). Где первый String - подпись опции, которую видит пользователь; второй String - значение опции, которое скрыто от пользователя; String* - указатель на rootVar (корневая переменная) элемента

    В завершении добавим три строчки после приведенного ниже комментария. Таким образом мы настроим контакты M5 на вывод:

    void setup() {
     ...
     /* Prepare user's I/O. For example pinMode(5, OUTPUT); */
     pinMode(SH_CP, OUTPUT);
     pinMode(ST_CP, OUTPUT);
     pinMode(DS, OUTPUT);
     ...
    }
    

    На этом всё! :) (рис. 7.2).

    Рисунок 7.2

    Шаг 8. SmartDrill и команда из Rangebox, Checkbox, Button (´。• ᵕ •。`)

    Что может объединить Rangebox, Checkbox и Button? Верно! - станок для сверления. Возьмём электродвигатель постоянного тока (например, от кассетного плеера), транзистор (чтоб по мощности подходил), резистор чтоб перекрывать ток базы, немного проводов, макетную плату и соберём! Бывает необходимо делать несколько отверстий одно за одним, а бывает необходимо сделать всего одно, поэтому возникает идея выделять некоторое время на работу дрели, а потом отключать её автоматически: тут нам на помощь приходит Checkbox.

    Рисунок 8

    С помощью Rangebox будем регулировать напряжение питания на электродвигателе. Кнопкой будем запускать и останавливать процесс (рис. 8). Обратите внимание - кнопка с иконкой ;)

    Кнопка Enter здесь нам не пригодится, поэтому Enter key для всех элементов останется пустым (нулем).
    Взамен мы будем вызывать пользовательскую функцию Drill с помощью свойства Callback для кнопки.

    Что у нас по коду? После RootVar's добавим bool startStatus, которая позволит программе понимать запущен ли двигатель или нет.

    /* RootVar's for UI elements (note: not edit manually) */
    ...
    // User's variables
    bool startStatus = false;
    

    Наполним пользовательскую функцию void Drill(String*):

    void Drill(String* rootVar) {
      startStatus = (startStatus) ? false : true;
      if (startStatus)
      {
        int power = UIRangebox_ztj619h.toInt() * 255 / 100;
        dac_out_voltage(DAC_CHANNEL_1, power);
        if (UICheckbox_1n9gs0b == "true")
        {
          UICaption("WAIT", &UIButton_enhu9fc);
          delay(25000);
          Drill(0);
          return;  
        }
        UICaption("STOP", &UIButton_enhu9fc);
      }
      else
      {
        dac_out_voltage(DAC_CHANNEL_1, 0);
        UICaption("START", &UIButton_enhu9fc);
      }
    }
    

    Для того, чтобы установить значение на аналоговом порту используют функцию dac_out_voltage(DAC_CHANNEL_1, int). Где DAC_CHANNEL_1 - номер канала (контакт 25), int - значение

    ;

    Для того, чтобы изменить заголовок любого из UI-элементов используют функцию UICaption(String, String*). Где String - новый заголовок; String* - указатель на rootVar (корневая переменная) элемента

    Ура! Теперь можно пробовать сверлить (рис. 8.1).

    Рисунок 8.1

    Шаг 9. Запуск!

    В разделе "Downloads" прилагаются видео с демонстрацией работы. На этом урок завершён.

    Downloads

    发布在 NEWS & LESSONS
  • RE: cannot boot M5Cloud firmware on M5Stack FIRE

    @bin 在 cannot boot M5Cloud firmware on M5Stack FIRE 中说:

    change SPI MODE: DIO

    You tried to burn the PSRAM version firmware in DIO mode. Is PSRAM still not initialized?

    发布在 FAQS
  • RE: How to set up Platformio 发布在 FAQS
  • RE: cannot boot M5Cloud firmware on M5Stack FIRE

    change SPI MODE: DIO

    发布在 FAQS
  • RE: cannot boot M5Cloud firmware on M5Stack FIRE

    What is the serial log?

    发布在 FAQS
  • RE: M5ez, a complete interface builder system for the M5Stack as an Arduino library. Extremely easy to use.

    Awesome!!!

    发布在 NEWS & LESSONS
  • RE: M5Stack Official ESP32 Camera Module - Demo, Runtime Error 发布在 PRODUCTS
  • RE: M5Stack Official ESP32 Camera Module - Demo, Runtime Error 发布在 PRODUCTS

与 M5Stack Community 的连接断开,我们正在尝试重连,请耐心等待