Posts Tagged ‘LCD’

How to align the red-green-blue (RGB) LCD panels (adjust convergence) of a Sharp XG-P10XU Projector

Thursday, July 17th, 2014

Projectors based on 3LCD technology work by splitting the white light from the lamp into 3 beams colored red, green, and blue, passing each beam through one of three LCD panels, combining the 3 beams back into one through a prism, and finally focusing the combined beam onto a wall or screen. In this process, the positions of the three individual LCD panels must be carefully controlled to ensure proper convergence. If a panel becomes misaligned, the corresponding color will be offset from the other colors in the image a condition known as misconvergence.

Small misalignments by a pixel or less are usually tolerable when displaying videos and motion pictures. When text is displayed however, even a misalignment of only one pixel can lead to blurry text that is hard to read. The problem is worst for small fonts whose characters may only be one to two pixels wide.

To fix the problem the convergence must be adjusted by realigning the LCD panels. Advanced projectors offer this option through the projector’s software interface but cheaper models lack any control over convergence. The Sharp NoteVision XG-P10XU is one such projector. The convergence is set at the factory and the unit sealed so that the user is forced to accept any misalignment in the purchased unit or that may develop over time. This post shows how to adjust the convergence of the Sharp NoteVision XG-P10XU 3 LCD projector by opening the case and accessing the optical bench inside. The process should be analogous for any 3LCD based projector.

The first step is to remove the external screws and top cover.  There are 15 screws total to remove and all can be removed with a philips screw driver. The screw positions are:

  • 2 screws on the left side of the unit
  • 2 screws on the right side of the unit
  • 1 screw on the front below the lens (secures the lens collar)
  • 6 large screws around the perimeter of the back side
  • 4 small screws on the back among all of the ports and connectors

projector left view projector lens collar screw projector rear view projector right view

 

The back cover should come off easily now. The blue lens collar on the front should be pulled off. It has small plastic tabs holding it in place. A knife can be used to pry the collar off.

projector rear cover off projector removing lens collar

Only after the back panel and lens collar are removed can the top cover by taken off. Once again, small plastic tabs make this slightly challenging but a knife inserted in the crevice between the top and bottom covers and bent up and down works well to separate the two. At the front two corners are small plastic pieces that will fall away. Be careful not to lose them down inside the projector. The top cover can only be pulled a few inches up from the unit because there are wires running to the speakers mounted on the cover as well as a ribbon cable running to the control panel. It is only necessary to unplug the speaker wires from the projector. Set the top cover off to the side a bit with the ribbon cable still attached. Later you will operate the projector in this state and it will be necessary to use the control panel.

projector opening case front projector opening case rear  projector under lid

That completes disassembly. You should now have access to the optical bench in the center of projector just behind the lens. You will see three ribbon cables that lead to each of the three LCD panels. The panels are mounted vertically and are hard to see clearly buried beneath all of the circuit boards. The square area between them holds the prism that recombines the beams and reflects them into the lens.

projector open not running

When standing at the rear of the projector so that it is pointed away from you, the left most panel is for the blue component, the center panel is green, and the right panel is red. If you look closely on the circuit boards near the ribbon cables that run to the panels will be the codes BP, GP, and RP for blue panel, green panel, and red panel, respectively. If you are attempting to adjust the panels on a different model and aren’t sure which is which, do not fret. Once the projector is turned on it will be obvious which panel is which.

WARNING! There are serious risks to operating the projector with the cover off. You are exposing yourself to dangerous voltages. DO NOT TOUCH ANY OF THE EXPOSED CIRCUITS OR WIRES. For maximum safety, wear latex or nitrile gloves. Be extremely careful not to short any of the circuits on the exposed PCB’s. Do not drop screws or metal tools onto the boards or into the unit. Try to have only one tool in your hand at a time and grasp it securely. Watch out for the cooling fans. Don’t stick anything in them, especially not your fingers. If you proceed to any of the following steps you do so at your own risk. I am not liable if you hurt yourself, the projector, or your surroundings.

To adjust the panels it will be necessary to operate the projector with the cover off. Plug in a video source and the unit’s power cable. Turn the projector on and focus it onto a white wall or screen in a dimly lit or dark room. It’s best. to connect a computer and have open a graphics-editing application. To gauge the alignment, I recommend long horizontal and vertical bars drawn in white on a black background. Make sure the bars are not anti-aliased. The pencil tools in MS Paint and GIMP work well for this. You may find that inverting the colors helps as well, especially to gauge the alignment of the blue panel. Test patterns can also be found online and displayed.

projector open and running

Inspect the displayed image and try to determine which colors are misaligned. The green panel in this projector is fixed as in most 3LCD projectors. You will be adjusting the red and blue. In the case of red and for the white line drawn on black, along the outer edge of the white line look for red pixels. If the panel is too far to the right, the outer right edge will be lined with red pixels and consequently the inner left edge will be lined with bluish-green pixels. For blue you’re looking for extra light blue pixels on the outer edge and yellow pixels on the inner edge.

Choose a panel to adjust first. You must loosen the retaining (locking) screws of the panel so that it can be adjusted. In this model, these are the two small black hex screws that run horizontally. Do not remove them, just loosen them a bit. You will need a hex wrench here. Now the panel can be adjusted by turning the hex bolts near the top of the panel. There is a bolt for vertical and a bolt for horizontal position. Some units will have screws instead of hex bolts and some may have a tilt adjustment as well. A pair of pliers may be needed to turn the adjustment bolts.

projector adjustment knobs locations

Adjustments should be in small increments. If you make a large adjustment, the beams will become severely misaligned. This might be a good way to determine which adjustment bolt moves what direction. Keep adjusting the bolts until you can no longer see extra colored pixels offset from the white bars (or black if on a white background). Go slowly and be patient. Sometimes, the best you can do is about +/- 1/2 pixel. When you feel satisfied with the adjustment, re-tighten the retaining screws (hex screws). Make sure they’re tight enough that bumps and heat won’t displace the panels again.

projector adjusting convergence

Repeat for the other panel and you’re finished. Turn off and unplug the projector. Then reverse the disassembly steps to replace the top cover, back cover, and lens collar. Don’t forget to plug the speakers back in. I recommend to tape the front plastic corner pieces in place until the unit is fully reassembled. Here’s hoping all went well.

 projector replacing cover taping corners

An improved key-reader library for the SainSmart LCD Keypad Shield (for Arduino)

Monday, August 5th, 2013

The LCD Keypad shield from SainSmart is a bargain. For ~$8 (and free shipping, at the time of this post) you get 32 character (16×2) blue/white LCD panel with a built-in keypad with 5 momentary switches. This provides a quick solution for interaction with Arduino projects. To control the LCD part of the shield, one can use the Arduino supplied LiquidCrystal library (included with Arduino IDE). In the Key_Grab demo (v. 0.2) on the SainSmart website is included a library, DFR_Key, for reading which keys are pressed on the keypad. However, the library is not written well. This post describes both the problem and the solution.

First, a little background is necessary about how the keypad signals a key is pressed. Only a single analog-in pin is used and the shield uses a voltage divider to send a voltage that corresponds to a given key. To detect a key, one has only to read the voltage at the analog pin and determine if it falls within a certain range. For example, a voltage of 0 to 0.7 V signals the UP key was pressed. The DFR_Key library contains a getKey() function that does this and returns an integer from 0 to 5 that represents the key pressed (0 is supposed to mean no key, but as written means the last key was just released).

You’d expect that when you call getKey() it would read the voltage at the pin, figure out what key that represented, and send back the integer representing the particular key. So really, it should just be translating the voltage to an integer from 0 to 5 (none, select, left, up, down, right, respectively). But, there is some “extra functionality” the library provides that is the problem. Here’s how the logic of the getKey() function works:

Has a minimum time passed since the last time I checked for a key press?

If not, do nothing – return no value at all!

If so, read the voltage at the pin. Is this voltage different than the voltage I read the last time I checked for a keypress?

If not, return -1.

If they’re different, it means a key was pressed right? Determine which key was pressed and return an integer from 0 to 5 representing that key.

The first bit of “extra functionality” is what the library refers to as the refreshRate. The idea is that you don’t want to check for a key press too quickly, else the function might return that the key is being held down when in fact it’s just a normal press. This makes some sense if you simply dump a getKey() call in your Arduino sketch’s loop() function. You would then check the returned value to see if it actually did a key press. If it decided enough time hadn’t pass it would return….oh wait! It doesn’t return anything in this case. That’s not appropriate behavior. When the program says getKey(), it should expect a key code sent back. Therefore, it should be the job of the programmer to only call getKey() at appropriate intervals (say every 100 ms).

That brings up the next problem. There are five keys on the keypad. Add in an extra code for “no key being pressed” and you get the six integers from 0 to 5. Perfectly reasonable. So what’s this -1 return value for? The library defines the alias SAMPLE_WAIT for this value (as opposed to NO_KEY, and UP_KEY, etc.). I’m not sure what the meaning was supposed to be, but this value is returned when the getKey() function determines that the key being pressed is the same as the key that was detected upon the last call to getKey(). At first, it would seem to be letting you know that the last key pressed is being held down. But 1: you don’t know what the last key pressed was, unless you’re tracking it yourself. And 2: that may not even be true – if you make two getKey() calls 60 s apart, whose to say whether the key was being held the whole time; all we know is that the same key was pressed as last time. So it’s telling us the same key was pressed as before and according to point 1, I’m keeping track of what that key was. If it had just returned the actual key code, I could have figured this out for myself by comparing it to my stored value of the last key pressed.

Now to the final problem. If you follow the logic stated above carefully, you’ll see that to determine if the same key was pressed, the getKey() function compares the voltage read at the analog pin to the voltage it read last time it detected a key was pressed. But the voltage does not directly correspond to a given key – a key press can be signaled by a range of voltages. For example, assume on the first call to getKey() it reads a value of 200 mV. That corresponds to the UP_KEY and it returns 3. On the next call to getKey() assume it reads a value of 205 mV. The user is pressing the up key again (or holding it down) but the voltage is slightly different. The getKey() function compares the new value, 205 mV, to the old value, 200 mV, and thinks a new key is being pressed. So instead of returning -1 for “same key is being pressed” it returns 3 for “up key is being pressed”.

Actually, this should be the behavior! Upon every call, the getKey() function should just return an integer representing the key that is being pressed at the time the call is made. But because the authors meant for it to return -1 when there was no change in the key being pressed, and meant for it to be called on every loop() iteration, the Key_Grab demo flickers the screen like crazy. Actually, it works fine when the UNO board is removed from all sources of noise and interference. But put it next to a piece of electronics (e.g. your computer) and the noise causes the voltage supplied to the analog pin to fluctuate, new key presses to be registered, and the demo to update the screen on every loop() iteration. It’s the constant updating that causes the flicker which makes it appear as though you got ripped off $10.

How can we fix this mess? Actually, the fixes are simple and actually reduce the code in the library.

  1. Remove all of the logic relating to the “refreshRate”. The programmer will be forced to decide how often to call getKey().
  2. Remove the comparison of the current key press to the previous key press. The programmer can decide if the user is pressing the same key by recording the last pressed key.

Here is the derived library which I’ve called LCD_Keypad_Reader.cpp (feel free to rename). The original SainSmart DFR_Key library didn’t come with a license so I’m not putting one on this derived work either. I don’t really care what you do with this code, but it’s possible that SainSmart could impose some kind of limitations.

#include "Arduino.h" 
#include "LCD_Keypad_Reader.h" 

static int DEFAULT_KEY_PIN = 0;  
static int DEFAULT_THRESHOLD = 5; 

// The Sainsmart keypad uses a voltage divider to deliver a voltage  
// between 0 and 5 V that corresponds to the key being pressed in  
// order to use only a single input pin. The values below are from 0 to  
// 1023 because the Arduino uses a 10 bit resolution. 
static int UPKEY_ARV = 144; // 0.720 V, that's read "analogue read value" 
static int DOWNKEY_ARV = 329; // 1.645 V 
static int LEFTKEY_ARV = 505; // 2.525 V 
static int RIGHTKEY_ARV = 0; // 0 V 
static int SELKEY_ARV = 742; // 3.710 V 
static int NOKEY_ARV = 1023; // 5.115 V 

LCD_Keypad_Reader::LCD_Keypad_Reader() 
{     
  _keyPin = DEFAULT_KEY_PIN; 
  _threshold = DEFAULT_THRESHOLD; 
  _curInput = NO_KEY; 
  _curKey = NO_KEY; 
} 

int LCD_Keypad_Reader::getKey() 
{ 
  _curInput =  analogRead(_keyPin); 
  _curKey = categorizeKey(_curInput); 
  return _curKey; 
} 

int LCD_Keypad_Reader::categorizeKey(int analogKeyValue){ 
  int categorizedKeyValue = 0; 

  if (analogKeyValue > UPKEY_ARV - _threshold && analogKeyValue < UPKEY_ARV + _threshold ){ 
      categorizedKeyValue = UP_KEY; 
  } 
  else if (analogKeyValue > DOWNKEY_ARV - _threshold && analogKeyValue < DOWNKEY_ARV + _threshold ){ 
      categorizedKeyValue = DOWN_KEY; 
  } 
  else if (analogKeyValue > RIGHTKEY_ARV - _threshold && analogKeyValue < RIGHTKEY_ARV + _threshold ){ 
      categorizedKeyValue = RIGHT_KEY; 
  } 
  else if (analogKeyValue > LEFTKEY_ARV - _threshold && analogKeyValue < LEFTKEY_ARV + _threshold ){  
      categorizedKeyValue = LEFT_KEY; 
  } 
  else if (analogKeyValue > SELKEY_ARV - _threshold && analogKeyValue < SELKEY_ARV + _threshold ){ 
      categorizedKeyValue = SELECT_KEY; 
  } 
  else{ 
    categorizedKeyValue = NO_KEY; 
  } 

  return categorizedKeyValue; 
}

And here is the header file, LCD_Keypad_Reader.h

#ifndef LCD_Keypad_Reader_h 
#define LCD_Keypad_Reader_h 

#include "Arduino.h" 

#define SAMPLE_WAIT -1 
#define NO_KEY 0 
#define UP_KEY 3 
#define DOWN_KEY 4 
#define LEFT_KEY 2 
#define RIGHT_KEY 5 
#define SELECT_KEY 1 

class LCD_Keypad_Reader 
{ 
  public: 
    LCD_Keypad_Reader(); 
    int getKey(); 
    int categorizeKey(int); 
  private: 
    int _keyPin; 
    int _threshold; 
    int _curInput; 
    int _curKey; 
}; 

#endif