help interfacing resistive screen with USB keyb.

I’d like to show a project I’ve been working and ask for some help with the code, I’m a UI designer, maker/hacker but not the best with code (o;

As a UI designer I spend a lot of time interacting with applications such as the adobe suite, lots of GUI interaction which can slow you down when you become a poweruser. Keyboard shortcuts aid power users but you still sometimes have to look at the keyboard for difficult combos - so my arduino ‘touchdesk’ design aims to allow me to interact with the software without taking focus away from the screen.

Imgur

The ‘system architecture’ is as follows
For the right hand: A wooden case containing a Wacom touch tablet for mouse pointer and pen input.

Left Hand: 7" digital picture frame with a resistive screen and 4 hard buttons above the screen (for things like copy/paste etc)

The resistive screen interfaces to an Arduino Illuminato which interprets the x/y coords and fires 1-15 of the digital i/o. That is, the sketch is designed to map x/y on to one of 15 areas on the screen (3 rows, 5 columns) and then with a custom shield containing an array for transistors talks to a generic usb keyboard* and on to the operating system.

Imgur

The problem I’m having is with the design of my code, I have little experience in code other than markup & css. As you can see from http://code.google.com/p/touchdesk/downloads/list or the code copied below. When a press is detected I match the x/y value against a set of constraints and then fire off one of the digital i/o pins. This happens constantly in a loop (with some minor delays)

However, this send in a rapid set of keypresses to the OS when I simply want to hold a key down

What I really need to do is that when a press is detected the sketch holds that corresponding i/o pin high until I lift my finger from the resistive screen.

I guess I could eventually work this out by myself but I’ve a bad habit of taking on too many projects- so I dont have spare time to learn how to accomplish this press & hold functionality. I’m wondering if someone has the time to review what I’m trying to accomplish and give me some pointers on the correct way forward. I’m not asking for a re-write (although that would be cool) but just a nod in the right direction!

/* TOUCH.PDE - Arduino sketch * TOUCH.PDE - Arduino sketch 
 * Read from a touch panel the touch position 
 * return it on serial port 
 *
 * Hardware used: 
 * Resistive touch panel, 4 wire 
 * Arduino Diecimila 
 *
 * April, 5th 2009 * April, 5th 2009 
 * by Marco Nicolato  
 * edited by Pauric O'Callaghan
 */

// Touch panel output wiring. These define the pins 
// used to apply voltages across the touch screen
#define bottomOutput 32    // LEFT to digital output 2 
#define rightOutput 31  // BOTTOM to digital output 3 
#define topOutput 30   // RIGHT to digital output 4 
#define leftOutput 33     // TOP to Digital output 5 


// Touch panel input wiring. These define the analog 
// input pins used to read the voltage from the screen
#define topInput 4      // TOP also to analog input 3 
#define leftInput 3    // RIGHT also to analog input 4 

// Button coordinates to pinout mapping
#define button1 2
#define button2 3
#define button3 4 //change due to screen Outputs
#define button4 5 //ditto
#define button5 19 //ditto
#define button6 20 //ditto
#define button7 8
#define button8 9
#define button9 10
#define button10 11
#define button11 12
#define button12 13
#define button13 14
#define button14 15
#define button15 16

// Values of where the screen was touched 0-1000
int touchX = 0; 
int touchY = 0; 

void setup()
{ 
  Serial.begin(9600); 
} 

void loop()
{  
  if (touched())
  { 
    Serial.print("X="); 
    Serial.print(touchX);  //prints X to the serial
    Serial.print(" Y="); 
    Serial.println(touchY); //prints Y to the serial
  }

}

// return TRUE if screen was touched, and coords in touchX and touchY
bool touched()
{
  bool touch = false;

  // Horizontal routine
  // 1: apply voltages to left & right
  // 2: turn top & bottom digital outputs off
  // 3: read top via analog inputs
  pinMode(bottomOutput, OUTPUT); 
  digitalWrite(bottomOutput, LOW);     // set Left = ground 
  pinMode(topOutput, OUTPUT); 
  digitalWrite(topOutput, HIGH);   // set Right = Vcc 
  
  pinMode(leftOutput, INPUT);         // Sets Top and Bottom to inputs
  pinMode(rightOutput, INPUT);      // to give them high impedence
  
  delay(10);  
  touchX = analogRead(topInput);   // wait a bit, then read from Top 

  
  // Vertical routine
  // 1: apply voltages to top & bottom
  // 2: turn left & right digital outputs off
  // 3: read right via analog inputs
  pinMode(rightOutput, OUTPUT); 
  digitalWrite(rightOutput, LOW); // Set Bottom to 0v
  pinMode(leftOutput, OUTPUT); 
  digitalWrite(leftOutput, HIGH);  // set Top to +Vcc

  pinMode(topOutput, INPUT); 
  pinMode(bottomOutput, INPUT); 
  
  delay(10);
  touchY = analogRead(leftInput); // wait a bit, then read from Right

  // Only if coords are below 1000 
  if(touchX < 1000 and touchY < 1000)
    touch = true; 

//3 column x 5 row button array
//There's probably a smarter way to detect x/y coordinates and do
//a little math to generate button presses on the array,
//but I ain't a clever coder.

// how each routine checks the coordinates
// if x value is between columns 1, 2 or 3 and y value is between 1,2,3,4 or 5
// write to the serial port - for debuggin purposes
// send the output port cooresponding to the row-column digital high
// wait for a short period
// send the output port digital low.


// Detect button 1
if (touchX < 950 and touchX > 662 and touchY > 70 and touchY < 292)
{Serial.print("button1");
digitalWrite (button1, HIGH);
delay(100);
digitalWrite (button1,LOW);}

// Detect button 2
if (touchX < 662 and touchX > 436 and touchY > 70 and touchY < 292)
{Serial.print("button2");
digitalWrite (button2, HIGH);
delay(100);
digitalWrite (button2,LOW);}

// Detect button 3
if (touchX < 436 and touchX > 100 and touchY > 70 and touchY < 292)
{Serial.print("button3");
digitalWrite (button3, HIGH);
delay(100);
digitalWrite (button3,LOW);}

// Detect button 4
if (touchX < 950 and touchX > 662 and touchY > 292 and touchY < 454)
{Serial.print("button4");
digitalWrite (button4, HIGH);
delay(100);
digitalWrite (button4,LOW);}

// Detect button 5
if (touchX < 662 and touchX > 436 and touchY > 292 and touchY < 454)
{Serial.print("button5");
digitalWrite (button5, HIGH);
delay(100);
digitalWrite (button5,LOW);}

// Detect button 6
if (touchX < 436 and touchX > 100 and touchY > 292 and touchY < 454)
{Serial.print("button6");
digitalWrite (button6, HIGH);
delay(100);
digitalWrite (button6,LOW);}

// Detect button 7
if (touchX < 950 and touchX > 662 and touchY > 454 and touchY < 616)
{Serial.print("button7");
digitalWrite (button7, HIGH);
delay(100);
digitalWrite (button7,LOW);}

// Detect button 8
if (touchX < 662 and touchX > 436 and touchY > 454 and touchY < 616)
{Serial.print("button8");
digitalWrite (button8, HIGH);
delay(100);
digitalWrite (button8,LOW);}

// Detect button 9
if (touchX < 436 and touchX > 100 and touchY > 454 and touchY < 616)
{Serial.print("button9");
digitalWrite (button9, HIGH);
delay(100);
digitalWrite (button9,LOW);}

// Detect button 10
if (touchX < 950 and touchX > 662 and touchY > 616 and touchY < 778)
{Serial.print("button10");
digitalWrite (button10, HIGH);
delay(100);
digitalWrite (button10,LOW);}

// Detect button 11
if (touchX < 662 and touchX > 436 and touchY > 616 and touchY < 778)
{Serial.print("button11");
digitalWrite (button11, HIGH);
delay(100);
digitalWrite (button11,LOW);}

// Detect button 12
if (touchX < 436 and touchX > 100 and touchY > 616 and touchY < 778)
{Serial.print("button12");
digitalWrite (button12, HIGH);
delay(100);
digitalWrite (button12,LOW);}

// Detect button 13
if (touchX < 950 and touchX > 662 and touchY > 778 and touchY < 990)
{Serial.print("button13");
digitalWrite (button13, HIGH);
delay(100);
digitalWrite (button13,LOW);}

// Detect button 14
if (touchX < 662 and touchX > 436 and touchY > 778 and touchY < 990)
{Serial.print("button14");
digitalWrite (button14, HIGH);
delay(100);
digitalWrite (button14,LOW);}

// Detect button 15
if (touchX < 436 and touchX > 100 and touchY > 778 and touchY < 990)
{Serial.print("button15");
digitalWrite (button15, HIGH);
delay(100);
digitalWrite (button15,LOW);}

// delay to slow down keypresses
delay(200);
  return touch; 
}

Feel free to ask any questions as I probably haven’t explained everything clearly

Cheers! /pauric

*I’m not strictly using a generic usb keyboard circuit, I’m using a Belkin Nostromo Gamepad. http://catalog.belkin.com/IWCatProductPage.process?Product_Id=164714 It has an agent that sits on the OS and can detect which Application is in focus. If I’m using Photoshop I get one set of keymapping, a different app and I get my favourite hotkeys for that app. I then swap the underlying image of ‘icons’ on the pictureframe to map to the app, note the two sets of wires in the top right of the 2nd image - thats the pictureframe back/next buttons. Ideally the OS would switch the images for me, but that’s another project (o;

I guess that was a lot of information for people to parse, unless I’m in the wrong forum - please let me know where I can go to get help. To clarify my problem

I have these routines

// Detect button 1
if (touchX < 950 and touchX > 662 and touchY > 70 and touchY < 292)
{Serial.print(“button1”);
digitalWrite (button1, HIGH);
delay(100);
digitalWrite (button1,LOW);}

The problem is this works but if I hold my finger on the screen I get lots of 100ms keypresses, I need it to act like a normal keyboard. So I need to change them in to something like

// Detect button 1
while (touchX < 950 and touchX > 662 and touchY > 70 and touchY < 292)
{Serial.print(“button1”);
digitalWrite (button1, HIGH);
delay(100);}
digitalWrite (button1,LOW);

The problem with this is that when it hits the first it sits there with nothing to break it out, at least I think that’s what is happening. I dont see anything on the serial console.

thanks /pauric

So, just remember that you've "pressed" button1, and next time around, if it is the same key, ignore it.
You only need one bit per key.

Groove: “So, just remember that you’ve “pressed” button1, and next time around, if it is the same key, ignore it.
You only need one bit per key.”

I’m sorry, I didnt follow that )o;

I think my problem (at least, this one of my many problems (o;) is that

while (touchX < 950 and touchX > 662 and touchY > 70 and touchY < 292)
{Serial.print(“button1”);
digitalWrite (button1, HIGH);
delay(100);}
digitalWrite (button1,LOW);

It sits in the first while waiting for touchx & touch y to be true. At least that was the pointer from a developer I’m working with. With that said, I should at least see one button come through on the serial and I’m not.

Any help appreciated /pauric

while (touchX < 950 and touchX > 662 and touchY > 70 and touchY < 292)

Have you got
#define and &&somewhere?

What I’d do is put the button bounds into a constant array, and iterate through the array to find if I’ve got an in-bounds touch.
Then decide if that key is the key I saw last time.

Groove

Have you got
Code:
#define and &&

I'm using an Illuminato from liquidware which has it's own flavour of the ide; AND is an operator in the ide, so there's no need to define it. The reason I'm using an illuminato is the extra i/o, I started this project before the mega came out, but I'd still use the illuminato, great design

What I'd do is put the button bounds into a constant array, and iterate through the array to find if I've got an in-bounds touch.
Then decide if that key is the key I saw last time.

As I said at the start in my long post, I'm not that familiar with code structures. I dont know what a constant array is. I'll look that up, learn it and get back either way. I really appreciate the help and pointers, this is a great learning exercise for me - one of the reasons I started this project as a someone with only hardware and gui design backgrounds, need to improve my code.

thanks again, /pauric

What I was saying was you’ve got lots of code like:

if (touchX < 436 and touchX > 100 and touchY > 292 and touchY < 454)
..
if (touchX < 950 and touchX > 662 and touchY > 454 and touchY < 616)
..
if (touchX < 662 and touchX > 436 and touchY > 454 and touchY < 616)
..
if (touchX < 436 and touchX > 100 and touchY > 454 and touchY < 616)
..
if (touchX < 950 and touchX > 662 and touchY > 616 and touchY < 778)
..
if (touchX < 662 and touchX > 436 and touchY > 616 and touchY < 778)
..
if (touchX < 436 and touchX > 100 and touchY > 616 and touchY < 778)

you could define a table with the bounds of each key, and, say the I/O pin associated with it:

typedef struct {
  const int xMin;
  const int xMax;
  const int yMin;
  const int yMax;
  const byte IO;
} ButtonDef;

ButtonDef buttons [] = { 
  {100, 436, 292, 454, 12},
  {662, 950, 454, 616, 13},
  {436, 662, 454, 616, 15}
...
...
};
...
int testButton (int touchX, int touchY)
{
  for (int i = 0; i < sizeof (buttons) / sizeof (buttons [0]); ++i) {
    if (touchX > buttons [i].xMin && 
        touchX < buttons [i].xMax &&
        touchY > buttons [i].yMin &&
        touchY < buttons [i].yMax) {
          return buttons [i].IO;
        }
  }
  return -1;
}

…and so on.

[edit]Hey - I’m a God! How did that happen?
Does this mean I have to gather disciples and start talking out of burning bushes and stuff?
Do I get to smite people?
That would be cool. :sunglasses: [/edit]

Hey - I'm a God! How did that happen?

Automatically when you hit 500 posts...

awesome!!!! thanks mate. Like I commented in the original code...

"//3 column x 5 row button array
//There's probably a smarter way to detect x/y coordinates and do
//a little math to generate button presses on the array,
//but I ain't a clever coder."

What I did kind of grew out of slowly iterating the code from correctly driving and then sensing the resistive plate on to then mapping sections of the plate to buttons. A classic case of inexperience resulting in inefficiency. I'll digest your suggestion and get to work on re-writing the array/mapping.

I appreciate you taking the time, cheers /pauric