Replacing Acer E5-476G LCD

I have Acer Aspire E5-476G which the LCD screen has a white screen on a quarter of it.
It also has vertical lines.
It is a common problem in Acer.
I never encounter an LCD problem in Dell after using it for 6 years

After searching, I found that it has 2 types.
HD 1366×768 Glossy or FHD 1920×1080 Matte
The price difference on AliExpress is only $3, but I can’t wait for 1 month if shipping from China.

I try to fix myself because Repair Shop charges me double of the LCD price.
Which is in between $50-$70 range

After searching on Youtube, I think I can do myself.
But I have a backup plan too. Which is find a local store with the cheapest LCD price and cheapest installation fee.
Installation fee only $3.5
So I bought from a local store. HD type only $32
I have 2 options, which are doing it myself and save $3.5 or let the shop do it for me.

If I do it myself, I’ll have experience on it and will be useful if the same thing happens next time

WHERE TO BUY:
https://www.bukalapak.com/p/komputer/aksesoris-226/aksesoris-lainnya-241/1gw8lhc-jual-led-lcd-14-0-slim-30-pin-laptop-acer-e5-476-e5-476g-es1-432-z476-z1402
https://www.aliexpress.com/item/32983308130.html

PREPARATIONS:
-Phillips screwdrivers
-guitar plectrum ( a small triangle plastic). You can use any thin plastic actually (ATM or CC card)

STEPS:

MicroSD Card Module

Image.png
Image.png
COMPONENTS:
-Arduino UNO
-MicroSD card module

CODE:
/*
  SD card read/write
This example shows how to read and write data to and from an SD card file
The circuit:
* SD card attached to SPI bus as follows:
** MOSI – pin 11
** MISO – pin 12
** CLK – pin 13
** CS – pin 4 (for MKRZero SD: SDCARD_SS_PIN)
created   Nov 2010
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
*/
#include <SPI.h>
#include <SD.h>
File myFile;
void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.print(“Initializing SD card…”);
  if (!SD.begin(4)) {
    Serial.println(“initialization failed!”);
    return;
  }
  Serial.println(“initialization done.”);
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open(“test.txt”, FILE_WRITE);
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print(“Writing to test.txt…”);
    myFile.println(“testing 1, 2, 3.”);
    // close the file:
    myFile.close();
    Serial.println(“done.”);
  } else {
    // if the file didn’t open, print an error:
    Serial.println(“error opening test.txt”);
  }
  // re-open the file for reading:
  myFile = SD.open(“test.txt”);
  if (myFile) {
    Serial.println(“test.txt:”);
    // read from the file until there’s nothing else in it:
    while (myFile.available()) {
      Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
  } else {
    // if the file didn’t open, print an error:
    Serial.println(“error opening test.txt”);
  }
}
void loop() {
  // nothing happens after setup
}

Keypad

COMPONENTS:
-Arduino Uno
-Keypad

Open Library Manager and install Keypad in there

CODE:
#include <Keypad.h>
const byte ROWS = 4;
const byte COLS = 4;
char hexaKeys[ROWS][COLS] = {
  {‘1’, ‘2’, ‘3’, ‘A’},
  {‘4’, ‘5’, ‘6’, ‘B’},
  {‘7’, ‘8’, ‘9’, ‘C’},
  {‘*’, ‘0’, ‘#’, ‘D’}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
void setup(){
  Serial.begin(9600);
}
void loop(){
  char customKey = customKeypad.getKey();
  if (customKey){
    Serial.println(customKey);
  }
}

Temperature Sensor

Image.png
Image.jpg
Image.png
COMPONENTS:
-Arduino Uno
-DS18B20 Temperature Sensor
-Resistor 4.7k
-LCD I2C
CODE:
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
// Set the LCD I2C address
LiquidCrystal_I2C lcd(0x27, 20, 4);
/********************************************************************/
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2
/********************************************************************/
// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
/********************************************************************/
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
/********************************************************************/
void setup(void)
{
  lcd.init();
  lcd.backlight();
  // start serial port
  Serial.begin(9600);
  Serial.println(“Dallas Temperature IC Control Library Demo”);
  // Start up the library
  sensors.begin();
}
void loop(void)
{
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  /********************************************************************/
  sensors.requestTemperatures(); // Send the command to get temperature readings
  /********************************************************************/
  Serial.print(“TEMP: “);
  Serial.print(sensors.getTempCByIndex(0)); // Why “byIndex”?
  Serial.print(‘\n’);
  // You can have more than one DS18B20 on the same bus.
  // 0 refers to the first IC on the wire
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(“TEMP:”);
  lcd.print(sensors.getTempCByIndex(0));
  lcd.print(“C”);
  delay(1000);
}

Soil Moisture Sensor

Image.png
Image.jpg
Image.png
COMPONENTS:
-Arduino Uno
-Soil Moisture Sensor
-LCD I2C

CODE:
//I2C LCD:
#include <Wire.h> // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>
// Set the LCD I2C address
LiquidCrystal_I2C lcd(0x27, 20, 4);
// These constants won’t change. They’re used to give names
// to the pins used:
const int analogInPin = A0; // Analog input pin that the Sensor is attached to
int sensorValue = 0; // value read from the Soil Moisture
void setup() {
  lcd.init();
  lcd.backlight();
  delay(100);
}
void loop() {
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(“Soil Moisture:”);// print the results to the LCD Display:
  sensorValue = analogRead(analogInPin);// read the analog in value:
  lcd.setCursor(0, 1);
  lcd.print(sensorValue);
  // wait 300 milliseconds before the next loop for the
  //analog-to-digital converter to settle after the last reading:
  delay(300);
}

Server Life Tester

Image.png

Image.png
Image.png

COMPONENTS:
-Arduino Uno
-Ethernet ENC28J60
-LCD I2C

CABLING:
ENC28J60 > Arduino
GND -> GND pin
VCC -> 5V pin
CS -> pin 10
SI -> pin 11
SO -> pin 12
SCK -> pin 13

Download and install Ethercard library from https://github.com/jcw/ethercard

CODE:
#include <avr/pgmspace.h>
#include <EtherCard.h>
#include <LiquidCrystal_I2C.h>
// Set the LCD I2C address
LiquidCrystal_I2C lcd(0x27, 20, 4);
#define CS_PIN        10
#define pinToToggle   9
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
// myip,gwip,mask,dns Only needed if using a Static IP
//static byte myip[]  = { 192,168,2,50 };
//static byte gwip[]  = { 192,168,2,1 };
//static byte mask[]  = { 255,255,255,0 };
//static byte dns[]   = { 8,8,8,8 };
byte Ethernet::buffer[700];
static int32_t timer;
static int polling;
//change these to the IPs that you want to ping
const char srv1[]  PROGMEM = “10.0.10.1”;
const char srv2[]  PROGMEM = “8.8.8.8”;
// Make sure this list matches the above list
const char* const servers[] PROGMEM = {srv1,srv2};
#define NUMSRVRS (sizeof(servers) / sizeof(servers[0]))
#define MAXCYCLES 3
#define PING_DELAY 2000000
static int cycles;
char sbuffer[30];
static int i;
float ms;
long interval              = 500;
unsigned long currentTime  = 0;
unsigned long previousTime = 0;
void blink() {
  currentTime = millis();
  if(currentTime – previousTime > interval) {
    previousTime = currentTime;
    digitalWrite(pinToToggle, !digitalRead(pinToToggle));
  }
}
static void gotPinged (byte* ptr) {
  ether.printIp(“>>> ping from: “, ptr);
}
void setup () {
  pinMode(pinToToggle,OUTPUT);
  lcd.init();
  lcd.backlight();
  Serial.begin(9600);
// Uncomment to wait till serial port is ready
//  while (!Serial) { }
  Serial.println(F(“Ping Servers\n”));
  if (!ether.begin(sizeof Ethernet::buffer, mymac, CS_PIN))
    Serial.println(F(“Failed to access Ethernet controller\n”));
  strcpy_P(sbuffer, (char*)pgm_read_word(&(servers[0])));
  ether.parseIp(ether.hisip,sbuffer);
// Comment these two lines and uncomment staticSetup
// to use static vs DHCP IP address
  if (!ether.dhcpSetup())
    Serial.println(F(“DHCP failed\n”));
//  if (!ether.staticSetup(myip, gwip, dns, mask))
//    Serial.println(F(“Failed to set Static IP”));
  while (ether.clientWaitingGw())
    ether.packetLoop(ether.packetReceive());
  Serial.println(“Gateway found”);
  ether.printIp(“IP:  “,     ether.myip);
  ether.printIp(“GW:  “,     ether.gwip);
  ether.printIp(“Netmask: “, ether.netmask);
  ether.printIp(“DNS IP: “,  ether.dnsip);
  Serial.println();
  ether.registerPingCallback(gotPinged);
  timer   = -9999999;
  polling = 0;
  i       = NUMSRVRS;
  cycles  = 0;
  digitalWrite(pinToToggle, !digitalRead(pinToToggle));
  delay(2000);
  digitalWrite(pinToToggle, !digitalRead(pinToToggle));
}
void loop () {
// Uncomment to change to no delay
// if ( ( (micros() – timer) >= PING_DELAY) || !polling  ) {
//Comment this next line, if the above line is uncommented
if ((micros() – timer) >= PING_DELAY) {
   if (polling) {
     ether.printIp(“\n”,ether.hisip);
     Serial.println(F(“Timeout\n”));
     lcd.setCursor(0, 1);
     lcd.print(“Timeout”);
     if (cycles >= MAXCYCLES) while (1) blink();
   }
   else {
     polling = 1;
     lcd.clear();
     lcd.setCursor(0, 0);
     ++i;
     if (i >= NUMSRVRS) i = 0;
     strcpy_P(sbuffer, (char*)pgm_read_word(&(servers[i])));
     lcd.print(sbuffer);
     ether.parseIp(ether.hisip,sbuffer);
     ether.printIp(“Pinging: “, ether.hisip);
   }
   cycles += 1;
   ether.clientIcmpRequest(ether.hisip);
   timer = micros();
  }
  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);
  if (len > 0 && ether.packetLoopIcmpCheckReply(ether.hisip)) {
    Serial.print(”  “);
    ms = (micros() – timer) * 0.001;
    Serial.print(ms, 3);
    Serial.println(” ms\n”);
    lcd.setCursor(0, 1);
    lcd.print(ms);
    lcd.print(” ms”);
    polling   = 0;
    cycles    = 0;
  }
}

Joystick with 2 Servos

Image.png
Image.png
Image.png
COMPONENTS:
-Arduino Uno
-Joystick
-2x Servos

CODE:
#include “Servo.h”;
Servo servo1;
Servo servo2;
int x_key = A0;
int y_key = A1;
int x_pos;
int y_pos;
int servo1_pin = 11;
int servo2_pin = 12;
int initial_position = 90;
int initial_position1 = 90;
void setup ( ) {
  Serial.begin (9600) ;
  servo1.attach (servo1_pin ) ;
  servo2.attach (servo2_pin ) ;
  servo1.write (initial_position);
  servo2.write (initial_position1);
  pinMode (x_key, INPUT) ;
  pinMode (y_key, INPUT) ;
}
void loop ( ) {
  x_pos = analogRead (x_key) ;
  y_pos = analogRead (y_key) ;
  if (x_pos < 300) {
    if (initial_position < 10) { } else {
      initial_position = initial_position – 20;
      servo1.write ( initial_position ) ;
      delay (100) ;
    }
  } if (x_pos > 700) {
    if (initial_position > 180)
    {
    }
    else {
      initial_position = initial_position + 20;
      servo1.write ( initial_position ) ;
      delay (100) ;
    }
  }
  if (y_pos < 300) {
    if (initial_position1 < 10) { } else {
      initial_position1 = initial_position1 – 20;
      servo2.write ( initial_position1 ) ;
      delay (100) ;
    }
  } if (y_pos > 700) {
    if (initial_position1 > 180)
    {
    }
    else {
      initial_position1 = initial_position1 + 20;
      servo2.write ( initial_position1 ) ;
      delay (100) ;
    }
  }
}

Gyro with Accelerometer Sensor

Image.png
Image.png
COMPONENTS:
-Arduino Uno
-MPU6050 3 Axis Gyro with Accelerometer

Download and extract i2cdevlib library from https://github.com/jrowberg/i2cdevlib
copy i2cdevlib-master/Arduino/I2Cdev into C:\Users\user1\Documents\Arduino\libraries
copy i2cdevlib-master/Arduino/MPU6050 into C:\Users\user1\Documents\Arduino\libraries

CODE:
#include “Wire.h” // This library allows you to communicate with I2C devices.
const int MPU_ADDR = 0x68; // I2C address of the MPU-6050. If AD0 pin is set to HIGH, the I2C address will be 0x69.
int16_t accelerometer_x, accelerometer_y, accelerometer_z; // variables for accelerometer raw data
int16_t gyro_x, gyro_y, gyro_z; // variables for gyro raw data
int16_t temperature; // variables for temperature data
char tmp_str[7]; // temporary variable used in convert function
char* convert_int16_to_str(int16_t i) { // converts int16 to string. Moreover, resulting strings will have the same length in the debug monitor.
  sprintf(tmp_str, “%6d”, i);
  return tmp_str;
}
void setup() {
  Serial.begin(9600);
  Wire.begin();
  Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
  Wire.write(0x6B); // PWR_MGMT_1 register
  Wire.write(0); // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
}
void loop() {
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
  Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
  Wire.requestFrom(MPU_ADDR, 7*2, true); // request a total of 7*2=14 registers
  // “Wire.read()<<8 | Wire.read();” means two registers are read and stored in the same variable
  accelerometer_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
  accelerometer_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
  accelerometer_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
  temperature = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
  gyro_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
  gyro_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
  gyro_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)
  // print out data
  Serial.print(“aX = “); Serial.print(convert_int16_to_str(accelerometer_x));
  Serial.print(” | aY = “); Serial.print(convert_int16_to_str(accelerometer_y));
  Serial.print(” | aZ = “); Serial.print(convert_int16_to_str(accelerometer_z));
  // the following equation was taken from the documentation [MPU-6000/MPU-6050 Register Map and Description, p.30]
  Serial.print(” | tmp = “); Serial.print(temperature/340.00+36.53);
  Serial.print(” | gX = “); Serial.print(convert_int16_to_str(gyro_x));
  Serial.print(” | gY = “); Serial.print(convert_int16_to_str(gyro_y));
  Serial.print(” | gZ = “); Serial.print(convert_int16_to_str(gyro_z));
  Serial.println();
  // delay
  delay(1000);
}

Sound Sensor

Image.png
Image.png
COMPONENTS:
-Arduino Uno
-Sound Sensor

Adjust potentiometer on Microphone so that LED on it almost off
We will use on-board led

CODE:
int ledPin = 13;
int sensorPin = 12;
boolean val = 0;
void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(sensorPin, INPUT);
  Serial.begin (9600);
}
void loop () {
  val = digitalRead(sensorPin);
  Serial.println (val);
  // when the sensor detects a signal above the threshold value, LED flashes
  if (val == HIGH) {
    digitalWrite(ledPin, HIGH);
  }
  else {
    digitalWrite(ledPin, LOW);
  }
}

Gas Sensor

Image.png
Image.jpg
Image.png
COMPONENTS:
-Arduino Uno
-LCD i2c
-MQ2 Gas Sensor

CODE:
//I2C LCD:
#include <Wire.h> // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>
// Set the LCD I2C address
LiquidCrystal_I2C lcd(0x27, 20, 4);
#define         MQ_PIN                       (0)     //define which analog input channel you are going to use
#define         RL_VALUE                     (5)     //define the load resistance on the board, in kilo ohms
#define         RO_CLEAN_AIR_FACTOR          (9.83)  //RO_CLEAR_AIR_FACTOR=(Sensor resistance in clean air)/RO,
//which is derived from the chart in datasheet
/***********************Software Related Macros************************************/
#define         CALIBARAION_SAMPLE_TIMES     (50)    //define how many samples you are going to take in the calibration phase
#define         CALIBRATION_SAMPLE_INTERVAL  (500)   //define the time interal(in milisecond) between each samples in the
//cablibration phase
#define         READ_SAMPLE_INTERVAL         (50)    //define how many samples you are going to take in normal operation
#define         READ_SAMPLE_TIMES            (5)     //define the time interal(in milisecond) between each samples in
//normal operation
/**********************Application Related Macros**********************************/
#define         GAS_LPG                      (0)
#define         GAS_CO                       (1)
#define         GAS_SMOKE                    (2)
/*****************************Globals***********************************************/
float           LPGCurve[3]  =  {2.3, 0.21, -0.47}; //two points are taken from the curve.
//with these two points, a line is formed which is “approximately equivalent”
//to the original curve.
//data format:{ x, y, slope}; point1: (lg200, 0.21), point2: (lg10000, -0.59)
float           COCurve[3]  =  {2.3, 0.72, -0.34};  //two points are taken from the curve.
//with these two points, a line is formed which is “approximately equivalent”
//to the original curve.
//data format:{ x, y, slope}; point1: (lg200, 0.72), point2: (lg10000,  0.15)
float           SmokeCurve[3] = {2.3, 0.53, -0.44}; //two points are taken from the curve.
//with these two points, a line is formed which is “approximately equivalent”
//to the original curve.
//data format:{ x, y, slope}; point1: (lg200, 0.53), point2: (lg10000,  -0.22)
float           Ro           =  10;                 //Ro is initialized to 10 kilo ohms
void setup()
{
  Serial.begin(9600);                               //UART setup, baudrate = 9600bps
  Serial.print(“Calibrating…\n”);
  Ro = MQCalibration(MQ_PIN);                       //Calibrating the sensor. Please make sure the sensor is in clean air
  //when you perform the calibration
  Serial.print(“Calibration is done…\n”);
  Serial.print(“Ro=”);
  Serial.print(Ro);
  Serial.print(“kohm”);
  Serial.print(“\n”);
  lcd.init();
  lcd.backlight();
}
void loop()
{
  Serial.print(“SMOKE:”);
  Serial.print(MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_SMOKE));
  Serial.print( “ppm” );
  Serial.print(”    “);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(“SMOKE:”);
  lcd.print(MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_SMOKE));
  Serial.print(“CO:”);
  Serial.print(MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_CO));
  Serial.print( “ppm” );
  Serial.print(”    “);
  lcd.setCursor(13, 0);
  lcd.print(“CO:”);
  lcd.setCursor(0, 1);
  lcd.print(MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_CO));
  Serial.print(“LPG:”);
  Serial.print(MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_LPG));
  Serial.print( “ppm” );
  Serial.print(”    “);
  Serial.print(“\n”);
  lcd.setCursor(7, 1);
  lcd.print(“LPG:”);
  lcd.print(MQGetGasPercentage(MQRead(MQ_PIN) / Ro, GAS_LPG));
  delay(200);
}
/****************** MQResistanceCalculation ****************************************
  Input:   raw_adc – raw value read from adc, which represents the voltage
  Output:  the calculated sensor resistance
  Remarks: The sensor and the load resistor forms a voltage divider. Given the voltage
         across the load resistor and its resistance, the resistance of the sensor
         could be derived.
************************************************************************************/
float MQResistanceCalculation(int raw_adc)
{
  return ( ((float)RL_VALUE * (1023 – raw_adc) / raw_adc));
}
/***************************** MQCalibration ****************************************
  Input:   mq_pin – analog channel
  Output:  Ro of the sensor
  Remarks: This function assumes that the sensor is in clean air. It use
         MQResistanceCalculation to calculates the sensor resistance in clean air
         and then divides it with RO_CLEAN_AIR_FACTOR. RO_CLEAN_AIR_FACTOR is about
         10, which differs slightly between different sensors.
************************************************************************************/
float MQCalibration(int mq_pin)
{
  int i;
  float val = 0;
  for (i = 0; i < CALIBARAION_SAMPLE_TIMES; i++) {      //take multiple samples
    val += MQResistanceCalculation(analogRead(mq_pin));
    delay(CALIBRATION_SAMPLE_INTERVAL);
  }
  val = val / CALIBARAION_SAMPLE_TIMES;                 //calculate the average value
  val = val / RO_CLEAN_AIR_FACTOR;                      //divided by RO_CLEAN_AIR_FACTOR yields the Ro
  //according to the chart in the datasheet
  return val;
}
/*****************************  MQRead *********************************************
  Input:   mq_pin – analog channel
  Output:  Rs of the sensor
  Remarks: This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
         The Rs changes as the sensor is in the different consentration of the target
         gas. The sample times and the time interval between samples could be configured
         by changing the definition of the macros.
************************************************************************************/
float MQRead(int mq_pin)
{
  int i;
  float rs = 0;
  for (i = 0; i < READ_SAMPLE_TIMES; i++) {
    rs += MQResistanceCalculation(analogRead(mq_pin));
    delay(READ_SAMPLE_INTERVAL);
  }
  rs = rs / READ_SAMPLE_TIMES;
  return rs;
}
/*****************************  MQGetGasPercentage **********************************
  Input:   rs_ro_ratio – Rs divided by Ro
         gas_id      – target gas type
  Output:  ppm of the target gas
  Remarks: This function passes different curves to the MQGetPercentage function which
         calculates the ppm (parts per million) of the target gas.
************************************************************************************/
int MQGetGasPercentage(float rs_ro_ratio, int gas_id)
{
  if ( gas_id == GAS_LPG ) {
    return MQGetPercentage(rs_ro_ratio, LPGCurve);
  } else if ( gas_id == GAS_CO ) {
    return MQGetPercentage(rs_ro_ratio, COCurve);
  } else if ( gas_id == GAS_SMOKE ) {
    return MQGetPercentage(rs_ro_ratio, SmokeCurve);
  }
  return 0;
}
/*****************************  MQGetPercentage **********************************
  Input:   rs_ro_ratio – Rs divided by Ro
         pcurve      – pointer to the curve of the target gas
  Output:  ppm of the target gas
  Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
         of the line could be derived if y(rs_ro_ratio) is provided. As it is a
         logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
         value.
************************************************************************************/
int  MQGetPercentage(float rs_ro_ratio, float *pcurve)
{
  return (pow(10, ( ((log(rs_ro_ratio) – pcurve[1]) / pcurve[2]) + pcurve[0])));
}