Saturday, May 6, 2017

Programming the MeinEnigma - Switches

For the next installment of programming the MeinEnigma hardware, we'll look at something simple: reading the positions of the rotary function switch and the "big red switch".



The red switch, used to reset and erase all settings, is connected to analog pin A6 of the Arduino. It is, however, used only at digital levels. I initially tried reading it using the digitalRead() function, bought found that it didn't work. It turns out that while this works for most Arduinos, the documentation mentions that for the Arduino Nano "Analog pins 6 and 7 cannot be used as digital pins." So you need to read the level using analogRead(). Since the values for analog inputs can range from 0 to 1023, a good test is against the mid-point of the range, 512, to determine if it is high or low.



The position switch uses the trick I described in an earlier blog post: it switches some resistor dividers so that the voltage on analog pin A7 changes depending on the switch position. This allows the five switch positions to be read using only one input.

The values change in steps of 1/4 of the full value of 1024, corresponding to 0, 1/4, 2/4, 3/4, and 4/4 of the full value. To test the values you can check against the middle of the values between these, which is what the MeinEnigma code and my example do. The table below shows the typical expected analog values for each switch position, and the ranges used to test. Note that the ranges correspond to 1/8, 3/8, 5/8, and 7/8 of the full 1024 value.

PositionRange Typical Value
Offsame as 5
1896 < val1023  (4/4)
2640 < val < 896768  (3/4)
3384 < val < 640512  (2/4)
4128 < val < 384256  (1/4)
5val < 1280  (0/4)


The Off position is used to power off the MeinEnigma when running on battery power, but when it is powered by USB the unit is powered up and the switch is equivalent to position 5 (fully clockwise). Another quirk that i mentioned in an early post is that if the big red switch is pressed, the unit is also powered up when on battery power.

The example program reads and displays the levels of the red switch and the function switch. Typical output is shown below:

Red switch  = 1023 (released)  Mode switch = 1023 (pos 1)
Red switch  =    0 (pressed)   Mode switch = 1023 (pos 1)
Red switch  = 1023 (released)  Mode switch = 1023 (pos 1)
Red switch  = 1023 (released)  Mode switch = 771 (pos 2)
Red switch  = 1023 (released)  Mode switch = 514 (pos 3)
Red switch  = 1023 (released)  Mode switch = 259 (pos 4)
Red switch  = 1023 (released)  Mode switch = 0 (pos 5)

Here is the full source code:

/*
  MeinEnigma Example

  Read the values of the function switch and the big red switch.
  See results through Arduino IDE serial monitor set to 9600 bps.

  Jeff Tranter

*/

// Pin numbers for the switches.
#define RED_SWITCH  A6
#define MODE_SWITCH A7

void setup() {
  Serial.begin(9600);           // Initialize serial port.
  pinMode(RED_SWITCH,  INPUT);  // Initialize both pins as inputs.
  pinMode(MODE_SWITCH, INPUT);
}

void loop() {

  // Red switch goes to an analog input but is at a digital level.
  // High when released, low when pressed.
  int val = analogRead(RED_SWITCH);
  Serial.print("Red switch  = ");
  Serial.print(val);
  if (val < 512) {
    Serial.print(" (pressed)");
  } else {
    Serial.print(" (released)");
  }

  // Mode switch returns different values depending on position.
  // Can figure out the position based on the value.
  val = analogRead(MODE_SWITCH);
  Serial.print("  Mode switch = ");
  Serial.print(val);
  if (val < 1024 * 1/8) {
    Serial.println(" (pos 5)");
  } else if (val < 1024 * 3/8) {
    Serial.println(" (pos 4)");
  } else if (val < 1024 * 5/8) {
    Serial.println(" (pos 3)");
  } else if (val < 1024 * 7/8) {
    Serial.println(" (pos 2)");
  } else {
    Serial.println(" (pos 1)");
  }

  delay(500);  // Wait for a half second.
}

No comments: