LTE Project: Button it up.

Now that I shoved all the wires in there and soldered in the connections for the buttons, I was able to close the case. It still opens, you just have to unscrew the 4 screws to take it apart.

With that, I’ve also made progress on the button reading and programming. As we saw before, the program uses a “truth table” where based on the math formula of (btn# + screenNumber)*screenNumber = menu option, we can calculate all possible outputs and assign them to operations or values.

So, this is a compilation of four different commits:

  1. Update the truth table and screens.
  2. Adding button reading.
  3. Screen updates.
  4. Some small updates.

You can check out all of the above commits to see the process, but here I’ll cover the main part. This is the button reading function.

int read_LCD_buttons(){               // read the buttons
  adc_key_in = 0;
    //adc_key_in = analogRead(A0);       // read the value from the sensor 
    Serial.print("anolog0:"); Serial.println(adc_key_in);
    if (adc_key_in > 550)   return btnRIGHT;
    //adc_key_in = analogRead(A1);       // read the value from the sensor 
    Serial.print("anolog1:"); Serial.println(adc_key_in);
    if (adc_key_in > 550)   return btnUP;
    adc_key_in = analogRead(A2);       // read the value from the sensor 
    Serial.print("anolog2:"); Serial.println(adc_key_in);
    if (adc_key_in > 550)   return btnDOWN;
    adc_key_in = analogRead(A3);       // read the value from the sensor 
    Serial.print("anolog3:"); Serial.println(adc_key_in);
    if (adc_key_in > 550)   return btnLEFT;
    adc_key_in = analogRead(A4);       // read the value from the sensor 
    Serial.print("anolog4:"); Serial.println(adc_key_in);
    if (adc_key_in > 550)   return btnSELECT;
    adc_key_in = analogRead(A5);       // read the value from the sensor 
    Serial.print("anolog5:"); Serial.println(adc_key_in);
    if (adc_key_in > 550)   return btnBACK; 
    return btnNONE;                // when all others fail, return this.
}

At first, I have it log everything to serial so I can see what is happening. Essentially, I took a wire from 3.3vdc that goes to the button. Then the button goes to the analog input, with a jumper going to a resistor to ground. That way, when you are not pushing the button, then the analog pin is not floating, and reads 0. When you push a button, that input reads around 700. So, I put the threshold at greater than 550. This seems to work fairly well.

The only problem is that I didn’t arrange the buttons the way I thought that I was programming them to work. Rather than swap the button wires physically, I just re-ordered them in my program, saying one was two, etc.

Here is the call inside the loop, asking for which button is pressed:

int waiting = 0;
menuNumber = 0;
while ( waiting < 30 ){
waiting++;
delay(10);
lcd_key = read_LCD_buttons(); // read the buttons
// TESTING ONLY // Serial.print(lcd_key);
switch (lcd_key){

case btnUP:{
menuNumber = (1+screenNumber)*screenNumber;
break;
}
case btnDOWN:{
menuNumber = (2+screenNumber)*screenNumber;
break;
}
case btnLEFT:{
menuNumber = (3+screenNumber)*screenNumber;
break;
}
case btnRIGHT:{
menuNumber = (4+screenNumber)*screenNumber;
break;
}
case btnSELECT:{
menuNumber = 255;
break;
}
case btnBACK:{
menuNumber = 256;
break;
}
}
// TESTING ONLY // Serial.print(menuNumber);
}

The above call checks every 10 milliseconds to see if you pressed a button. After 30 checks, it continues through the process and refreshes the screens, etc. This works out to be about a half second, due to the length of the program. There is a small window of about a tenth of a second, where pushing a button doesn’t do anything, but I’ve found in test runs that it was really rare that pushing a button didn’t respond immediately.

If you don’t do this, it is refreshing the screen about 30 times a second as it rips through the program, and there is only a fraction of a second where pushing the button actually works. There is probably a better way to do this, but this works really well for my program.

Now I just need to make it send and receive text messages!

Linux – keep it simple.

LTE project button code

lteprojecta

Here’s the deal, I have a very small screen, with six available buttons. I need to make sure that if you press the button, it does the right thing for the screen it is currently on. How do I map the six buttons to the specific screen I’m on, with only 32 kb of programming space?

Well, brilliant or butchered, here’s what I did….

First, I decided on the flow of screens. Example, from the main screen (screen number 1), you can go to the texting screen (sn 6) or GPS screen (sn 3) or the “other programs” screen (sn 12). From the GPS screen, you can go to the location screen (sn 2), or the compass screen (sn 4). And from the texting screen, you can go to the read messages screen (sn 9), or the send messages screen (sn 7), the delete all messages screen (sn 8), and so on and so forth. All told, there is around 15 screens currently.

But how to map pushing the same four buttons for each screen number? There are probably better ways to do this, but I came up with a mathematical formula and a switch to handle this for me.

sn Button 1 Button 2 Button 3 Button 4 Button 5 Button 6
1 2 3 4 5
2 6 8 10 12
3 12 15 18 21
4 20 24 28 32
5 30 35 40 45
6 42 48 54 60
7 56 63 70 77
8 72 80 88 96
9 90 99 108 117
10 110 120 130 140
11 132 143 154 165
12 156 168 180 192
13 182 195 208 221
14 210 224 238 252
15 240 255 270 285
16 272 288 304 320
17 306 323 340 357
18 342 360 378 396
19 380 399 418 437

What the above table does, is utilize the following formula: “Screen number plus Button number is multiplied by Screen number.” With this formula, I then used the variable screen number, which I need for what screen text to display anyways, and made a switch that checks the math to see what button I am pushing. What is interesting about this is that you technically could do any operation from any screen, but the screen number will make the math work only for the operations you should do on that screen.

As you can see, screen number 2 and screen number 3 both share the number 12. In my small table, it is the only occurrence of the same number twice. Fortunately, it is okay, because I made screen 2 the location screen, which you get to from screen 3. So pushing that first button on screen 3 takes you mathematically to screen 2, and on screen 2, pressing the last button takes you mathematically to screen 2, which is where location information is displayed. So it is a little sloppy, but works out in the end.

Buttons 5 and 6 don’t work that way, though. They are special buttons that always return the same two numbers. The first one is the “home” button, which from any screen takes you back to the main menu. The second is the “select” button, which will be unique in use and will have to have a special case by case use. It’s actually not used on any screens thus far, so it is held in reservation for now. I was thinking of making it a modem power on/off switch, but we will see.

As always, you can check out the commit on my GitLab.

Linux – keep it simple.