t08 - olikraus/m2tklib GitHub Wiki

Tutorial 8: Software Design for User Forms

The discussed questions are:

  • How to transfer information from and to M2tklib?
  • How to process user input?

This tutorial will:

  • Suggest a simple concept for the design of user input forms.
  • Apply this concept to a more complex example (PWM Pin List)

Theory

Background: Most M2tklib elements just get the address of a variable. Here is M2_U8NUM

M2_U8NUM(el_u8_field, NULL, 0, 255, &my_variable);

The value of my_variable can be modified by the user. Such a variable is called a "menu variable".

The suggestion in this tutorial is to write two procedures:

  • Collect information and store the information in the "menu variables" (prepare_user_input procedure).
  • Collect values from the "menu variables", apply these values to the hardware and/or store these values (apply_user_input procedure).

http://wiki.m2tklib.googlecode.com/hg/pic/user_interface.png

Example

This example is available as PWMPinList in the Arduino IDE.

Specification

  • The user can select one of the PWM pins (six for the Arduino Uno).
  • The user can modify the output state of each pin.
  • Output states are: Low, high, duty cycle time of 25%, 50% and 75%

Pin Array

The user can select a pin:

https://github.com/bj0rky/m2tklibwiki/blob/master/u8g_pwm_pin_list.png

The output state will be stored in the array pwm_duty_array:

// array with all the information
#define PWM_PIN_CNT 6
uint8_t pwm_duty_array[PWM_PIN_CNT] = { 0,0,0,0,0,0 };
uint8_t pwm_pin_array[PWM_PIN_CNT] = { 3,5,6,9,10,11 };

An internal number from 0 to 4 will be mapped to the intended output state:

void pwm_value_to_str(uint8_t value, char *dest) {
  switch(value) {
    case 0: strcpy(dest, "low"); break;
    case 1: strcpy(dest, "25%"); break;
    case 2: strcpy(dest, "50%"); break;
    case 3: strcpy(dest, "75%"); break;
    case 4: strcpy(dest, "high"); break;
  }
}

Menu Variables

The user menu for one pwm pin will look like this:

http://wiki.m2tklib.googlecode.com/hg/pic/u8g/u8g_pwm_dialog.png

The values of two variables are visible:

uint8_t pwm_menu_pin = 0;  // pin number
uint8_t pwm_menu_duty = 0;  // output state

As suggested, there are two procedures to transfer data from and to the menu:

// get pin and value pair from the global array and store them in the menu variables
void pwm_prepare_user_input(void) {
  pwm_menu_duty = pwm_duty_array[pwm_menu_current_index];
  pwm_menu_pin = pwm_pin_array[pwm_menu_current_index];
}

// write user input back to the array and to the analog pin
void pwm_apply_user_input(void) {
  // write user input into array
  pwm_duty_array[pwm_menu_current_index] = pwm_menu_duty;
  pwm_pin_array[pwm_menu_current_index] = pwm_menu_pin;
  // apply user input to the hardware
  // analogWrite(pwm_menu_pin, pwm_value_to_analog(pwm_menu_value));
}

Program Flow

To jump from the list of pwm pins to the user dialog, use the following sequence:

    // transfer values from the array to the menu variables
    pwm_prepare_user_input();
    
    // give control to the pwm dialog
    m2.setRoot(&el_top_pwm_menu);

The "ok" button of the dialog menu for one pwm pin will jump back to the pin list. The callback procedure for the "ok" button will look like this:

// this procedure is called by the "ok" button
void pwm_fn_ok(m2_el_fnarg_p fnarg) {
  // finish user entry
  pwm_apply_user_input();
  
  // go back to parent menu
  m2.setRoot(&top_el_pin_list);
}

Conclusion

  • Use one procedure to setup the variables of your dialog menu.
  • Use one procedure to apply values from the user input to the rest of the software.

Links