Questions on Powering LCD & Servo on Separate Power

My project is having an arduino micro power a servo to open/close my computer Side panel, and an LCD that displays system information. Arduino Micro is powered by Powergen Cell Phone charger (which acts as UPS) which is charged by computer's PSU's 5VSB. I want the LCD to turn off with the computer, while the Servo/Arduino stays on when PC is off.

http://www.youtube.com/watch?v=D1EAKzHXK9A http://www.youtube.com/watch?v=QlLmXhrccFc http://www.youtube.com/watch?v=9K0unPHVsNA

My 2 questions:

  • How do I power the LCD from a separate power source - do I hook up just pins VCC/GRND (LCD Pins 1,2) to alternate power, or do I hook up all the pins that go to power, which would include 15-Backlight and 5-RW?
  • I am using a mini-servo, HS255BB. Can it be powered off the arduino micro or does it need it's own power? I've been testing it just hooked up to the arduino (which would be hooked up to usb) with no issue, but read a few things say this isn't okay...

Thanks.

Someone on reddit said this:

If you power down the LCD and 'drive' any one of the I/O there is a good chance you will fry the LCD, depending on the specific nature of the I/O of the LCD device. They may or may not have input protection and that input protection may or may not be able to tolerate sustained current. Driving the LCD I/O may prove to be a major drain on your battery. If you can't be certain, you will need to make sure this doesn't happen by using a buffer or something.

Belial88: My 2 questions:

  • How do I power the LCD from a separate power source - do I hook up just pins VCC/GRND (LCD Pins 1,2) to alternate power, or do I hook up all the pins that go to power, which would include 15-Backlight and 5-RW?
  • I am using a mini-servo, HS255BB. Can it be powered off the arduino micro or does it need it's own power? I've been testing it just hooked up to the arduino (which would be hooked up to usb) with no issue, but read a few things say this isn't okay...

Thanks.

Just an idea, it might be worth looking into powering your LCD using the spare power connectors that powers the DVD rom in your computer. You get the choice of 12V, 5V, and 3.3V

This will give you the convenience to turn on and off the LCD with the computer.

As for the servo, you would need to check its current requirement against the max current rating which the MCU pin is able to source.

Yes, that is something like what I'd be powering my LCD off of, the 5v rail off my PSU, or maybe the motherboard's internal USB headers.

My question is in regards to wiring. Do I put just the VCC/GRND pins onto those PC power rails, or do I put backlight and RW on them as well?

As for the servo, you would need to check its current requirement against the max current rating which the MCU pin is able to source.

I tested it with a pot and multi, i think the max it got up to was like .8 under stress.

Seriously? No one knows how to hook up an LCD to alternate power around here?

Belial88: My question is in regards to wiring. Do I put just the VCC/GRND pins onto those PC power rails, or do I put backlight and RW on them as well?

To power the LCD, you connect the GND of the LCD to GND of the PC power connector and make sure that the VCC of your LCD matches the voltage on the power connector pin.

In regards to the backlight, you should determine the voltage requirement before you connect that to the power connector. You would need to find this spec on the manual.

The R/W pin is a different matter from the above pins. From experience, the R/W pin of the LCD is a control pin to control data flow into(write) and out(read) of the LCD. If you only want to write to the LCD, you can tie this pin to VCC(1) or GND(0) depending on the LCD. The control signal require to select read or write should be outlined in the manual, so you would need to go thru the manual and find out the control state i.e. HIGH(1) or LOW(0) to read or write. You should also find out the voltage requirement for this pin before tie it to the VCC pin.

Belial88: I tested it with a pot and multi, i think the max it got up to was like .8 under stress.

0.8? The Arduino micro spec lists that DC Current per I/O Pin = 40 mA. http://arduino.cc/en/Main/arduinoBoardMicro#.Uwi7Qs4tAgA

The LCD is 5v, so of course I'd run off a 5v source (5v rail on psu, usb, it doesnt really matter which 5v source I choose, plenty to choose from). The RW is grounded, it's basically not used. Yea, just writing to the LCD via smartie.

0.8? The Arduino micro spec lists that DC Current per I/O Pin = 40 mA. http://arduino.cc/en/Main/arduinoBoardMicro#.Uwi7Qs4tAgA

Well that's for the signal on servo. The Servo's power of course comes from the arduino's 5v pin, which I think is up to 1amp. I'm not too worried about the servo.

So the conclusion I came up with the LCD, is that I need to somehow tell the arduino to stop sending signals to the LCD, and I need to use an analogue pin (because my digital's are all used up) to sense voltage on this alternate power. I'd need to write to code some sort of If Voltage > 1 (or whatever, ie more than 0 to detect on/off), LCDpwer=on, and otherwise off. I'm not sure how to do that exactly... code to follow.

Seriously, what a useless forum. I can’t post my code beause it exceeds post length? How am I supposed to post my code

#include <VarSpeedServo.h>  //variable speed servo library
#include <LiquidCrystal.h>

//declare the constants to be used
#define LEDPIN 13             //pin attached to LED
#define servoPIN 9            //Servo control line
#define SWitchPIN 2           //input from N.O. momentary switch
#define redPIN 12             //PWM pin for red LED backlight
#define greenPIN 11           //PWM pin for green LED backlight
#define bluePIN 10            //PWM pin for blue LED backlight
#define rsPIN 8               //reset pin for LCD
#define enablePIN 3           //enable pin for LCD
#define d4PIN 4               //data pin4 for LCD
#define d5PIN 5               //data pin5 for LCD
#define d6PIN 6               //data pin6 for LCD
#define d7PIN 7               //data pin7 for LCD
// these constants won't change.  But you can change the size of
// your LCD using them:
const int numRows = 4;
const int numCols = 20;
const int ignoreMAX = 6;      //ignore this many characters
const unsigned long wait = 50;//wait time for ADC update after last Smartie cmd
#define posOpenCMD 1900       //Define Clockwise Servo position in usec
#define posCloseCMD 600       //Define CounterClockwise Servo position in usec
#define DBdelay 2000          //Min time needed btw any 2 button presses, in msec
#define fastSPD 100           //speed setting; 1 = slowest, 255 is fastest (???)
#define slowSPD 15            //Speed Servo/Door opens and closes (15 is good average)
#define DIV_1    1.0          //gain correction for A0 channel
#define DIV_2    1.0          //note it's 1.0, not 1, to get full floating point accuracy

#define V_REF    2.54         //use the measured Aref voltage

//declare the variables used
boolean updateFlag = false;          //flag to refresh ADC readings
volatile boolean doorOPEN = false;   //desired door state set to closed
byte rxbyte = 0;                     //rxbyte is the received byte from Smartie
byte temp = 0;
int ignoreCNT = 0;                   //count of characters to ignore
int row = 0;                         //index of last row position
int col = 0;                         //index of last col position
int rowA0 = 0;                       //index of A0 row position
int colA0 = 0;                       //index of A0 col position
int rowA1 = 0;                       //index of A1 row position
int colA1 = 0;                       //index of A1 col position
unsigned long MSGtime = 0;           //holds the time of the last cursor cmd
volatile unsigned long SWtime = 0;   //holds the time of the last valid switch push
float voltage1 = 0.0;                // calculated voltage for A0
float voltage2 = 0.0;                // calculated voltage for A1

LiquidCrystal lcd(rsPIN, enablePIN, d4PIN, d5PIN, d6PIN, d7PIN);
VarSpeedServo myServo; //create a servo object

void setup() {
  //set the pins to be ins or outs
  pinMode(LEDPIN, OUTPUT);
  digitalWrite(LEDPIN, LOW);            //turn LED off
  pinMode(servoPIN, OUTPUT);
  pinMode(SWitchPIN, INPUT_PULLUP);
  pinMode(redPIN, OUTPUT);
  pinMode(greenPIN, OUTPUT);
  pinMode(bluePIN, OUTPUT);

  attachInterrupt(1, SW_ISR, FALLING);

  Serial.begin(9600);

  lcd.begin(numCols, numRows);
  delay(50);
  lcd.clear();
  delay(5);

  analogWrite(bluePIN,0);                //Blue brightness 255-0
  analogWrite(redPIN,255);               //Red brightness 255-0
  analogWrite(greenPIN,255);             //Green brightness 255-0

  analogReference(INTERNAL);              //use the internal 2.56v ADC reference

  //CMD the servo to close the door
  myServo.attach(servoPIN);               // Attach the servo
  myServo.slowmove(posCloseCMD, fastSPD); // Tell servo to go to closed position

  //put a hello world on the LCD
  lcd.print("Line 1");
  lcd.setCursor(3, 1);
  lcd.print("Line 2");
  lcd.setCursor(8, 2);
  lcd.print("Line 3");
  lcd.setCursor(13, 3);
  lcd.print("Line 4");
  delay(2000);
}

//the following function is the ISR that responds to the push button switch
//it commands the door to open or close at slow speed
void SW_ISR(){
  //debounce the switch by ignoring any interrupt that occurs too soon after the prior one
  unsigned long Time = millis();
  if((Time - SWtime > DBdelay) && (Time > SWtime)){//enough time has elapsed, not a bounce
    SWtime = Time;                                 //save new time of switch push
    doorOPEN = !doorOPEN;                          //reverse desired door state
    if(doorOPEN == true){
      digitalWrite(LEDPIN, HIGH);                  //turn LED on
      myServo.slowmove(posOpenCMD, slowSPD);       //tell servo to go to open position
    }
    else {
      digitalWrite(LEDPIN, LOW);                   //turn LED off
      myServo.slowmove(posCloseCMD, slowSPD);      //tell servo to go to closed position
    }
  }
}

//this function is used by the smartie code to get data from the PC
byte serial_getch(){
  int incoming;
  while (Serial.available()==0){
    //check to see if enough time has passed since last message from PC
    if((millis() - MSGtime > wait) && (updateFlag == true)){
      updateADC();
    }
  }
  // read the incoming byte:
  incoming = Serial.read();
  return (byte) (incoming &0xff);
}

//this function will update the ADC readings if the [ or ] have been sent
void updateADC(){
  updateFlag = false;
  if(colA0 > 0){
    voltage1 = DIV_1 * float(analogRead(A0)) * V_REF/1023.0;
    lcd.setCursor(colA0, rowA0);
    lcd.print(voltage1, 3);
  }
  if(colA1 > 0){
    voltage2 = DIV_2 * float(analogRead(A1)) * V_REF/1023.0;
    lcd.setCursor(colA1, rowA1);
    lcd.print(voltage2, 3);
  }
}
//the main loop is now just the hacked version of the Arduino Smartie code
void loop(){
  rxbyte = serial_getch();   //this calls the 'function' serial_getch(), stores result in rxbyte
  if (rxbyte == 254)     //Matrix uses 254 for commands, if rxbyte = 254 the the code below runs
  {
    ignoreCNT == 0;          //turn off character ignoring whenever a command is sent
    switch (serial_getch())  //calls serial_getch() to get the next byte from the PC
    {
    case 66: //former backlight on command
      break;
    case 70: //former backlight off command
      break;
    case 71:  //set cursor position
      MSGtime = millis();           //remember time that cursor cmd was sent
      updateFlag = true;            //set flag to update ADC readings
      row = 0;
      col = 0;
      temp = (serial_getch() - 1);  //get column byte
      switch (serial_getch())       //get row byte
      {
        //line 1 is already set up
      case 2:
        row = 1;
        temp += 0x40;
        break;
      case 3:
        row = 2;
        temp += 0x14;
        break;
      case 4:
        row = 3;
        temp += 0x54;
        break;
      default:
        break;
      }
      lcd.command(0b10000000 + temp);
      break;
    case 72:  //cursor home (reset display position)
      lcd.command(2);
      break;
    case 74:  //show underline cursor
      lcd.command(0b00001110);
      break;
    case 75:  //underline cursor off
    case 84:  //block cursor off
      lcd.command(0b00001100);
      break;
    case 76:  //move cursor left
      lcd.command(16);
      break;
    case 77:  //move cursor right
      lcd.command(20);
      break;
    case 78:  //define custom char
      lcd.command(64 + (serial_getch() * 8));  //get+set char address
      for (temp = 7; temp != 0; temp--)
      {
        lcd.print(serial_getch()); //get each pattern byte
      }
      break;
    case 83:  //show blinking block cursor
      lcd.command(0b00001111);
      break;
    case 86:  //GPO OFF
      //implement later
      break;
    case 87:  //GPO ON
      /*temp = serial_getch();
       if (temp == 1)
       {
       GPO1 = GPO_ON;
       }*/
      break;
    case 88:  //clear display, cursor home
      lcd.command(1);
      break;
    case 152: //set and remember (doesn't save value, though)
    case 153: //set backlight brightness
      //not implemented
      break;

      //these commands ignored (no parameters)
    case 35: //read serial number
    case 36: //read version number
    case 55: //read module type
    case 59: //exit flow-control mode
    case 65: //auto transmit keypresses
    case 96: //auto-repeat mode off (keypad)
    case 67: //auto line-wrap on
    case 68: //auto line-wrap off
    case 81: //auto scroll on
    case 82: //auto scroll off
    case 104: //init horiz bar graph
    case 109: //init med size digits
    case 115: //init narrow vert bar graph
    case 118: //init wide vert bar graph
      break;
    default:
      //all other commands ignored and parameter byte discarded
      temp = serial_getch();  //dump the command code
      break;
    }
    return;
  } //END OF COMMAND HANDLER

  //change accented char to plain, detect and change descenders
  //NB descenders only work on 5x10 displays. This lookup table works
  //  with my DEM-20845 (Display Elektronik GmbH) LCD using KS0066 chip.
  switch (rxbyte)
  {
    //chars that have direct equivalent in LCD charmap
    /* case 0x67: //g
     rxbyte = 0xE7;
     break;
     case 0x6A: //j
     rxbyte = 0xEA;
     break;
     case 0x70: //p
     rxbyte = 0xF0;
     break;
     case 0x71: //q
     rxbyte = 0xF1;
     break;
     case 0x79: //y
     rxbyte = 0xF9;
     break;
     */
  case 0x5B: //Formerly [, now does A0 ADC
    voltage1 = DIV_1 * float(analogRead(A0)) * V_REF/1023.0;           
    lcd.print(voltage1, 3);
    rxbyte = 0x76;           //will cause v to be displayed
    ignoreCNT = ignoreMAX;   //ignore characters replaced by ADC reading
    updateFlag = false;      //reset ADC update flag
    rowA0 = row;             //store row of A0 reading
    colA0 = col;             //store col of A0 reading
    break;
  case 0x5D: //Formerly ], now does A1 ADC
    voltage2 = DIV_2 * float(analogRead(A1)) * V_REF/1023.0;
    lcd.print(voltage2, 3);
    rxbyte = 0x76;           //will cause v to be displayed
    ignoreCNT = ignoreMAX;   //ignore characters replaced by ADC reading
    updateFlag = false;      //reset ADC update flag
    rowA1 = row;             //store row of A1 reading
    colA1 = col;             //store col of A1 reading
    break;
  case 0xE4: //ASCII "a" umlaut
    rxbyte = 0xE1;
    break;
  case 0xF1: //ASCII "n" tilde
    rxbyte = 0xEE;
    break;
  case 0xF6: //ASCII "o" umlaut
    rxbyte = 0xEF; //was wrong in v0.86
    break;
  case 0xFC: //ASCII "u" umlaut
    rxbyte = 0xF5;
    break;

    //accented -> plain equivalent
    //and misc symbol translation
  case 0xA3: //sterling (pounds)
    rxbyte = 0xED;
    break;
    /* case 0xB0: //degrees symbol
     rxbyte = 0xDF;
     break;
     */
  case 0xB5: //mu
    rxbyte = 0xE4;
    break;
  case 0xC0: //"A" variants
  case 0xC1:
  case 0xC2:
  case 0xC3:
  case 0xC4:
  case 0xC5:
    rxbyte = 0x41;
    break;
  case 0xC8: //"E" variants
  case 0xC9:
  case 0xCA:
  case 0xCB:
    rxbyte = 0x45;
    break;
  case 0xCC: //"I" variants
  case 0xCD:
  case 0xCE:
  case 0xCF:
    rxbyte = 0x49;
    break;
  case 0xD1: //"N" tilde -> plain "N"
    rxbyte = 0x43;
    break;
  case 0xD2: //"O" variants
  case 0xD3:
  case 0xD4:
  case 0xD5:
  case 0xD6:
  case 0xD8:
    rxbyte = 0x4F;
    break;
  case 0xD9: //"U" variants
  case 0xDA:
  case 0xDB:
  case 0xDC:
    rxbyte = 0x55;
    break;
  case 0xDD: //"Y" acute -> "Y"
    rxbyte = 0x59;
    break;
    /*  case 0xDF: //beta  //mucks up LCDSmartie's degree symbol??
     rxbyte = 0xE2;
     break;
     */
  case 0xE0: //"a" variants except umlaut
  case 0xE1:
  case 0xE2:
  case 0xE3:
  case 0xE5:
    rxbyte = 0x61;
    break;
  case 0xE7: //"c" cedilla -> "c"
    rxbyte = 0x63;
    break;
  case 0xE8: //"e" variants
  case 0xE9:
  case 0xEA:
  case 0xEB:
    rxbyte = 0x65;
    break;
  case 0xEC: //"i" variants
  case 0xED:
  case 0xEE:
  case 0xEF:
    rxbyte = 0x69;
    break;
  case 0xF2: //"o" variants except umlaut
  case 0xF3:
  case 0xF4:
  case 0xF5:
  case 0xF8:
    rxbyte = 0x6F;
    break;
  case 0xF7: //division symbol
    rxbyte = 0xFD;
    break;
  case 0xF9: //"u" variants except umlaut
  case 0xFA:
  case 0xFB:
    rxbyte = 0x75;
    break;
  default:
    break;
  }
  if(ignoreCNT > 0){
    ignoreCNT--;
  }
  if(ignoreCNT == 0){
    col++;              //increment column position counter
    lcd.write(rxbyte);  //otherwise a plain char so we print it to lcd
  }
}