build a homemade diy tft lcd driver breakout board pcb manufacturer

Along 3 years I have been trying several leg mechanism, at first I decided to do a simple desing with tibial motor where placed on femur joint.This design had several problems, like it wasn"t very robust and the most importat is that having the motor (with big mass) that far from the rotating axis, caused that in some movements it generate unwanted dynamics to the robot body, making controlability worse.New version have both motors of femur/tibial limb at coxa frame, this ends with a very simple setup and at the same time, the heaviest masses of the mechanism are centered to the rotating axis of coxa limb, so even though the leg do fast movements, inertias won"t be strong enough to affect the hole robot mass, achieving more agility.Inverse Kinematics of the mechanismAfter building it I notice that this mechanism was very special for another reason, at the domain the leg normally moves, it acts as a diferential mecanism, this means that torque is almost all the time shared between both motor of the longer limbs. That was an improvent since with the old mechanism tibial motor had to hold most of the weight and it was more forced than the one for femur.To visualize this, for the same movement, we can see how tibial motor must travel more arc of angel that the one on the new version.In order to solve this mechanism, just some trigonometry is needed. Combining both cosine and sine laws, we can obtain desired angle (the one between femur and tibia) with respect to the angle the motor must achieve.Observing these equations, with can notice that this angle (the one between femur and tibia) depends on both servos angles, which means both motors are contributing to the movement of the tibia.Calibration of servosAnother useful thing to do if we want to control servo precisely is to print a calibration tool for our set up. As shown in the image below, in order to know where real angles are located, angle protactor is placer just in the origin of the rotating joint, and choosing 2 know angles we can match PWM signal to the real angles we want to manipulate simply doing a lineal relation between angles and PWM pulse length.Then a simple program in the serial console can be wrtten to let the user move the motor to the desired angle. This way the calibration process is only about placing motor at certain position and everything is done and we won"t need to manually introduce random values that can be a very tedious task.With this I have achieved very good calibrations on motors, which cause the robot to be very simetrial making the hole system more predictable. Also the calibration procedure now is very easy to do, as all calculations are done automatically. Check Section 1 for the example code for calibration.More about this can be seen in the video below, where all the building process is shown as well as the new leg in action.SECTION 1:In the example code below, you can see how calibration protocol works, it is just a function called calibrationSecuence() which do all the work until calibration is finished. So you only need to call it one time to enter calibration loop, for example by sending a "c" character thought the serial console.Also some useful function are used, like moving motor directly with analogWrite functions which all the calculations involved, this is a good point since no interrupts are used.This code also have the feature to calibrate the potentiometer coming from each motor.#define MAX_PULSE 2500 #define MIN_PULSE 560 /*---------------SERVO PIN DEFINITION------------------------*/ int m1 = 6;//FR int m2 = 5; int m3 = 4; int m4 = 28;//FL int m5 = 29; int m6 = 36; int m7 = 3;//BR int m8 = 2; int m9 = 1; int m10 = 7;//BL int m11 = 24; int m12 = 25; int m13 = 0;//BODY /*----------------- CALIBRATION PARAMETERS OF EACH SERVO -----------------*/ double lowLim[13] = {50, 30, 30, 50, 30, 30, 50, 30, 30, 50, 30, 30, 70}; double highLim[13] = {130, 150, 150, 130, 150, 150, 130, 150, 150, 130, 150, 150, 110}; double a[13] = { -1.08333, -1.06667, -1.07778, //FR -1.03333, 0.97778, 1.01111, //FL 1.03333, 1.05556, 1.07778, //BR 1.07500, -1.07778, -1.00000, //BL 1.06250 }; double b[13] = {179.0, 192.0, 194.5, //FR 193.0, 5.5, -7.5, //FL 7.0, -17.0, -16.0, //BR -13.5, 191.5, 157.0, //BL -0.875 }; double ae[13] = {0.20292, 0.20317, 0.19904 , 0.21256, -0.22492, -0.21321, -0.21047, -0.20355, -0.20095, -0.20265, 0.19904, 0.20337, -0.20226 }; double be[13] = { -18.59717, -5.70512, -2.51697, -5.75856, 197.29411, 202.72169, 185.96931, 204.11902, 199.38663, 197.89534, -5.33768, -32.23424, 187.48058 }; /*--------Corresponding angles you want to meassure at in your system-----------*/ double x1[13] = {120, 135, 90, 60, 135 , 90, 120, 135, 90, 60, 135, 90, 110}; //this will be the first angle you will meassure double x2[13] = {60, 90, 135, 120, 90, 135, 60, 90, 135, 120, 90, 135, 70};//this will be the second angle you will meassure for calibration /*--------You can define a motor tag for each servo--------*/ String motorTag[13] = {"FR coxa", "FR femur", "FR tibia", "FL coxa", "FL femur", "FL tibia", "BR coxa", "BR femur", "BR tibia", "BL coxa", "BL femur", "BL tibia", "Body angle" }; double ang1[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; double ang2[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; float xi[500]; float yi[500]; float fineAngle; float fineL; float fineH; int motorPin; int motor = 0; float calibrationAngle; float res = 1.0; float ares = 0.5; float bres = 1.0; float cres = 4.0; float rawAngle; float orawAngle; char cm; char answer; bool interp = false; bool question = true; bool swing = false; int i; double eang; int freq = 100; // PWM frecuency can be choosen here. void connectServos() { analogWriteFrequency(m1, freq); //FR coxa digitalWrite(m1, LOW); pinMode(m1, OUTPUT); analogWriteFrequency(m2, freq); //femur digitalWrite(m2, LOW); pinMode(m2, OUTPUT); analogWriteFrequency(m3, freq); //tibia digitalWrite(m3, LOW); pinMode(m3, OUTPUT); analogWriteFrequency(m4, freq); //FL coxa digitalWrite(m4, LOW); pinMode(m4, OUTPUT); analogWriteFrequency(m5, freq); //femur digitalWrite(m5, LOW); pinMode(m5, OUTPUT); analogWriteFrequency(m6, freq); //tibia digitalWrite(m6, LOW); pinMode(m6, OUTPUT); analogWriteFrequency(m7, freq); //FR coxa digitalWrite(m7, LOW); pinMode(m7, OUTPUT); analogWriteFrequency(m8, freq); //femur digitalWrite(m8, LOW); pinMode(m8, OUTPUT); analogWriteFrequency(m9, freq); //tibia digitalWrite(m9, LOW); pinMode(m9, OUTPUT); analogWriteFrequency(m10, freq); //FR coxa digitalWrite(m10, LOW); pinMode(m10, OUTPUT); analogWriteFrequency(m11, freq); //femur digitalWrite(m11, LOW); pinMode(m11, OUTPUT); analogWriteFrequency(m12, freq); //tibia digitalWrite(m12, LOW); pinMode(m12, OUTPUT); analogWriteFrequency(m13, freq); //body digitalWrite(m13, LOW); pinMode(m13, OUTPUT); } void servoWrite(int pin , double angle) { float T = 1000000.0f / freq; float usec = float(MAX_PULSE - MIN_PULSE) * (angle / 180.0) + (float)MIN_PULSE; uint32_t duty = int(usec / T * 4096.0f); analogWrite(pin , duty); } double checkLimits(double angle , double lowLim , double highLim) { if ( angle >= highLim ) { angle = highLim; } if ( angle <= lowLim ) { angle = lowLim; } return angle; } int motorInfo(int i) { enc1 , enc2 , enc3 , enc4 , enc5 , enc6 , enc7 , enc8 , enc9 , enc10 , enc11 , enc12 , enc13 = readEncoders(); if (i == 0) { rawAngle = enc1; motorPin = m1; } else if (i == 1) { rawAngle = enc2; motorPin = m2; } else if (i == 2) { rawAngle = enc3; motorPin = m3; } else if (i == 3) { rawAngle = enc4; motorPin = m4; } else if (i == 4) { rawAngle = enc5; motorPin = m5; } else if (i == 5) { rawAngle = enc6; motorPin = m6; } else if (i == 6) { rawAngle = enc7; motorPin = m7; } else if (i == 7) { rawAngle = enc8; motorPin = m8; } else if (i == 8) { rawAngle = enc9; motorPin = m9; } else if (i == 9) { rawAngle = enc10; motorPin = m10; } else if (i == 10) { rawAngle = enc11; motorPin = m11; } else if (i == 11) { rawAngle = enc12; motorPin = m12; } else if (i == 12) { rawAngle = enc13; motorPin = m13; } return rawAngle , motorPin; } void moveServos(double angleBody , struct vector anglesServoFR , struct vector anglesServoFL , struct vector anglesServoBR , struct vector anglesServoBL) { //FR anglesServoFR.tetta = checkLimits(anglesServoFR.tetta , lowLim[0] , highLim[0]); fineAngle = a[0] * anglesServoFR.tetta + b[0]; servoWrite(m1 , fineAngle); anglesServoFR.alpha = checkLimits(anglesServoFR.alpha , lowLim[1] , highLim[1]); fineAngle = a[1] * anglesServoFR.alpha + b[1]; servoWrite(m2 , fineAngle); anglesServoFR.gamma = checkLimits(anglesServoFR.gamma , lowLim[2] , highLim[2]); fineAngle = a[2] * anglesServoFR.gamma + b[2]; servoWrite(m3 , fineAngle); //FL anglesServoFL.tetta = checkLimits(anglesServoFL.tetta , lowLim[3] , highLim[3]); fineAngle = a[3] * anglesServoFL.tetta + b[3]; servoWrite(m4 , fineAngle); anglesServoFL.alpha = checkLimits(anglesServoFL.alpha , lowLim[4] , highLim[4]); fineAngle = a[4] * anglesServoFL.alpha + b[4]; servoWrite(m5 , fineAngle); anglesServoFL.gamma = checkLimits(anglesServoFL.gamma , lowLim[5] , highLim[5]); fineAngle = a[5] * anglesServoFL.gamma + b[5]; servoWrite(m6 , fineAngle); //BR anglesServoBR.tetta = checkLimits(anglesServoBR.tetta , lowLim[6] , highLim[6]); fineAngle = a[6] * anglesServoBR.tetta + b[6]; servoWrite(m7 , fineAngle); anglesServoBR.alpha = checkLimits(anglesServoBR.alpha , lowLim[7] , highLim[7]); fineAngle = a[7] * anglesServoBR.alpha + b[7]; servoWrite(m8 , fineAngle); anglesServoBR.gamma = checkLimits(anglesServoBR.gamma , lowLim[8] , highLim[8]); fineAngle = a[8] * anglesServoBR.gamma + b[8]; servoWrite(m9 , fineAngle); //BL anglesServoBL.tetta = checkLimits(anglesServoBL.tetta , lowLim[9] , highLim[9]); fineAngle = a[9] * anglesServoBL.tetta + b[9]; servoWrite(m10 , fineAngle); anglesServoBL.alpha = checkLimits(anglesServoBL.alpha , lowLim[10] , highLim[10]); fineAngle = a[10] * anglesServoBL.alpha + b[10]; servoWrite(m11 , fineAngle); anglesServoBL.gamma = checkLimits(anglesServoBL.gamma , lowLim[11] , highLim[11]); fineAngle = a[11] * anglesServoBL.gamma + b[11]; servoWrite(m12 , fineAngle); //BODY angleBody = checkLimits(angleBody , lowLim[12] , highLim[12]); fineAngle = a[12] * angleBody + b[12]; servoWrite(m13 , fineAngle); } double readEncoderAngles() { enc1 , enc2 , enc3 , enc4 , enc5 , enc6 , enc7 , enc8 , enc9 , enc10 , enc11 , enc12 , enc13 = readEncoders(); eang1 = ae[0] * enc1 + be[0]; eang2 = ae[1] * enc2 + be[1]; eang3 = ae[2] * enc3 + be[2]; eang4 = ae[3] * enc4 + be[3]; eang5 = ae[4] * enc5 + be[4]; eang6 = ae[5] * enc6 + be[5]; eang7 = ae[6] * enc7 + be[6]; eang8 = ae[7] * enc8 + be[7]; eang9 = ae[8] * enc9 + be[8]; eang10 = ae[9] * enc10 + be[9]; eang11 = ae[10] * enc11 + be[10]; eang12 = ae[11] * enc12 + be[11]; eang13 = ae[12] * enc13 + be[12]; return eang1 , eang2 , eang3 , eang4 , eang5 , eang6 , eang7 , eang8 , eang9 , eang10 , eang11 , eang12 , eang13; } void calibrationSecuence( ) { //set servos at their middle position at firstt for (int i = 0; i <= 12; i++) { rawAngle , motorPin = motorInfo(i); servoWrite(motorPin , 90); } // sensorOffset0 = calibrateContacts(); Serial.println(" "); Serial.println("_________________________________SERVO CALIBRATION ROUTINE_________________________________"); Serial.println("___________________________________________________________________________________________"); Serial.println("(*) Don"t send several caracter at the same time."); delay(500); Serial.println(" "); Serial.println("Keyboard: "x"-> EXIT CALIBRATION. "c"-> ENTER CALIBRATION."); Serial.println(" "i"-> PRINT INFORMATION. "); Serial.println(" "); Serial.println(" "n"-> CHANGE MOTOR (+). "b" -> CHANGE MOTOR (-)."); Serial.println(" "m"-> START CALIBRATION."); Serial.println(" "q"-> STOP CALIBRATION."); Serial.println(" "); Serial.println(" "r"-> CHANGE RESOLUTION."); Serial.println(" "p"-> ADD ANGLE. "o"-> SUBTRACT ANGLE. "); Serial.println(" "s"-> SAVE ANGLE."); delay(500); Serial.println(" "); Serial.println("---------------------------------------------------------------------------------------------------"); Serial.print("SELECTED MOTOR: "); Serial.print(motorTag[motor]); Serial.print(". SELECTED RESOLUTION: "); Serial.println(res); while (CAL == true) { if (Serial.available() > 0) { cm = Serial.read(); if (cm == "x") { Serial.println("Closing CALIBRATION program..."); CAL = false; secuence = false; startDisplay(PAGE); angleBody = 90; anglesIKFR.tetta = 0.0; anglesIKFR.alpha = -45.0; anglesIKFR.gamma = 90.0; anglesIKFL.tetta = 0.0; anglesIKFL.alpha = -45.0; anglesIKFL.gamma = 90.0; anglesIKBR.tetta = 0.0; anglesIKBR.alpha = 45.0; anglesIKBR.gamma = -90.0; anglesIKBL.tetta = 0.0; anglesIKBL.alpha = 45.0; anglesIKBL.gamma = -90.0; } else if (cm == "i") { // + Serial.println(" "); Serial.println("---------------------------------------------------------------------------------------------------"); Serial.println("---------------------------------------------------------------------------------------------------"); Serial.println("(*) Don"t send several caracter at the same time."); delay(500); Serial.println(" "); Serial.println("Keyboard: "x"-> EXIT CALIBRATION. "c"-> ENTER CALIBRATION."); Serial.println(" "i"-> PRINT INFORMATION. "); Serial.println(" "); Serial.println(" "n"-> CHANGE MOTOR (+). "b" -> CHANGE MOTOR (-)."); Serial.println(" "m"-> START CALIBRATION."); Serial.println(" "q"-> STOP CALIBRATION."); Serial.println(" "); Serial.println(" "r"-> CHANGE RESOLUTION."); Serial.println(" "p"-> ADD ANGLE. "o"-> SUBTRACT ANGLE. "s"-> SAVE ANGLE."); Serial.println(" "); delay(500); Serial.println(" "); Serial.println("---------------------------------------------------------------------------------------------------"); Serial.println(" "); Serial.print("SELECTED MOTOR: "); Serial.print(motorTag[motor]); Serial.print(". SELECTED RESOLUTION: "); Serial.println(res); Serial.println("Actual parameters of the motor: "); Serial.print("High limit: "); Serial.print(highLim[motor]); Serial.print(" Low limit: "); Serial.print(lowLim[motor]); Serial.print(" Angle 1: "); Serial.print(ang1[motor]); Serial.print(" Angle 2: "); Serial.println(ang2[motor]); Serial.println("---------------------------------------------------------------------------------------------------"); } else if (cm == "m") { // + secuence = true; } else if (cm == "s") { // + } else if (cm == "n") { // + motor++; if (motor >= 13) { motor = 0; } Serial.print("SELECTED MOTOR: "); Serial.println(motorTag[motor]); } else if (cm == "b") { // + motor--; if (motor < 0) { motor = 13 - 1; } Serial.print("SELECTED MOTOR: "); Serial.println(motorTag[motor]); } else if (cm == "r") { // + if (res == ares) { res = bres; } else if (res == bres) { res = cres; } else if (res == cres) { res = ares; } Serial.print("SELECTED RESOLUTION: "); Serial.println(res); } } if (secuence == true) { Serial.print("Starting secuence for motor: "); Serial.println(motorTag[motor]); for (int i = 0; i <= 30; i++) { delay(20); Serial.print("."); } Serial.println("."); while (question == true) { unsigned long currentMicros = micros(); if (currentMicros - previousMicros >= 100000) { previousMicros = currentMicros; if (Serial.available() > 0) { answer = Serial.read(); if (answer == "y") { question = false; interp = true; secuence = true; } else if (answer == "n") { question = false; interp = false; secuence = true; } else { Serial.println("Please, select Yes(y) or No(n)."); } } } } answer = "t"; question = true; if (interp == false) { Serial.println("___"); Serial.println(" | Place motor at 1ts position and save angle"); Serial.println(" | This position can be the higher one"); rawAngle , motorPin = motorInfo(motor); calibrationAngle = 90; //start calibration at aproximate middle position of the servo. while (secuence == true) { /* find first calibration angle */ if (Serial.available() > 0) { cm = Serial.read(); if (cm == "p") { // + Serial.print(" | +"); Serial.print(res); Serial.print(" : "); calibrationAngle = calibrationAngle + res; servoWrite(motorPin , calibrationAngle); Serial.println(calibrationAngle); } else if (cm == "o") { // - Serial.print(" | -"); Serial.print(res); Serial.print(" : "); calibrationAngle = calibrationAngle - res; servoWrite(motorPin , calibrationAngle); Serial.println(calibrationAngle); } else if (cm == "r") { // + if (res == ares) { res = bres; } else if (res == bres) { res = cres; } else if (res == cres) { res = ares; } Serial.print("SELECTED RESOLUTION: "); Serial.println(res); } else if (cm == "q") { // quit secuence secuence = false; Serial.println(" | Calibration interrupted!!"); } else if (cm == "s") { // save angle ang1[motor] = calibrationAngle; secuence = false; Serial.print(" | Angle saved at "); Serial.println(calibrationAngle); } } } if (cm == "q") { Serial.println(" |"); } else { secuence = true; Serial.println("___"); Serial.println(" | Place motor at 2nd position and save angle"); Serial.println(" | This position can be the lower one"); } while (secuence == true) { /* find second calibration angle */ if (Serial.available() > 0) { cm = Serial.read(); if (cm == "p") { // + Serial.print(" | +"); Serial.print(res); Serial.print(" : "); calibrationAngle = calibrationAngle + res; servoWrite(motorPin , calibrationAngle); Serial.println(calibrationAngle); } else if (cm == "o") { // - Serial.print(" | -"); Serial.print(res); Serial.print(" : "); calibrationAngle = calibrationAngle - res; servoWrite(motorPin , calibrationAngle); Serial.println(calibrationAngle); } else if (cm == "r") { // + if (res == ares) { res = bres; } else if (res == bres) { res = cres; } else if (res == cres) { res = ares; } Serial.print("SELECTED RESOLUTION: "); Serial.println(res); } else if (cm == "q") { // quit secuence secuence = false; Serial.println(" | Calibration interrupted!!"); } else if (cm == "s") { // save angle ang2[motor] = calibrationAngle; secuence = false; Serial.print(" | Angle saved at "); Serial.println(calibrationAngle); } } } /*--------------------start calibration calculations------------------*/ if (cm == "q") { Serial.println("___|"); Serial.println("Calibration finished unespected."); Serial.println(" Select another motor."); Serial.print("SELECTED MOTOR: "); Serial.print(motorTag[motor]); Serial.print(". SELECTED RESOLUTION: "); Serial.println(res); } else { Serial.println("___"); Serial.println(" |___"); Serial.print( " | | Interpolating for motor: "); Serial.println(motorTag[motor]); secuence = true; //real angle is calculated interpolating both angles to a linear relation. a[motor] = (ang2[motor] - ang1[motor]) / (x2[motor] - x1[motor]); b[motor] = ang1[motor] - x1[motor] * (ang2[motor] - ang1[motor]) / (x2[motor] - x1[motor]); Serial.println(" | |"); } interp = true; } /*---------------------------make swing movement to interpolate motor encoder-----*/ if (interp == true and secuence == true) { delay(200); double x; int k = 0; int stp = 180; swing = true; i = 0; orawAngle , motorPin = motorInfo(motor); previousMicros = 0; while (swing == true) { // FIRST unsigned long currentMicros = micros(); if (currentMicros - previousMicros >= 10000) { // save the last time you blinked the LED previousMicros = currentMicros; x = x2[motor]; calibrationAngle = a[motor] * x + b[motor]; servoWrite(motorPin , calibrationAngle); rawAngle , motorPin = motorInfo(motor); if ((i % 3) == 0) { yi[k+1] = x; xi[k] = rawAngle; Serial.print(" | | Real ang: "); Serial.print(x); Serial.print(" -> Servo ang: "); Serial.print(calibrationAngle); Serial.print(" Enc: "); Serial.println(rawAngle); k++; } if (i >= stp) { swing = false; } i++; } } swing = true; i = 0; while (swing == true) { // moving unsigned long currentMicros = micros(); if (currentMicros - previousMicros >= 10000) { // save the last time you blinked the LED previousMicros = currentMicros; x = x2[motor] + float(i) * (x1[motor] - x2[motor]) / stp; calibrationAngle = a[motor] * x + b[motor]; servoWrite(motorPin , calibrationAngle); rawAngle , motorPin = motorInfo(motor); if ((i % 6) == 0) { yi[k+1] = x; xi[k] = rawAngle; Serial.print(" | | Real ang: "); Serial.print(x); Serial.print(" -> Servo ang: "); Serial.print(calibrationAngle); Serial.print(" Enc: "); Serial.println(rawAngle); k++; } if (i >= stp) { swing = false; } i++; } } swing = true; i = 0; while (swing == true) { // SECOND unsigned long currentMicros = micros(); if (currentMicros - previousMicros >= 10000) { // save the last time you blinked the LED previousMicros = currentMicros; x = x1[motor]; calibrationAngle = a[motor] * x + b[motor]; servoWrite(motorPin , calibrationAngle); rawAngle , motorPin = motorInfo(motor); if ((i % 3) == 0) { yi[k+1] = x; xi[k] = rawAngle; Serial.print(" | | Real ang: "); Serial.print(x); Serial.print(" -> Servo ang: "); Serial.print(calibrationAngle); Serial.print(" Enc: "); Serial.println(rawAngle); k++; } if (i >= stp) { swing = false; } i++; } } swing = true; i = 0; while (swing == true) { // moving unsigned long currentMicros = micros(); if (currentMicros - previousMicros >= 10000) { // save the last time you blinked the LED previousMicros = currentMicros; x = x1[motor] + float(i) * (x2[motor] - x1[motor]) / stp; calibrationAngle = a[motor] * x + b[motor]; servoWrite(motorPin , calibrationAngle); rawAngle , motorPin = motorInfo(motor); if ((i % 6) == 0) { yi[k+1] = x; xi[k] = rawAngle; Serial.print(" | | Real ang: "); Serial.print(x); Serial.print(" -> Servo ang: "); Serial.print(calibrationAngle); Serial.print(" Enc: "); Serial.println(rawAngle); k++; } if (i >= stp) { swing = false; } i++; } } swing = true; i = 0; while (swing == true) { // FIRST unsigned long currentMicros = micros(); if (currentMicros - previousMicros >= 10000) { // save the last time you blinked the LED previousMicros = currentMicros; x = x2[motor]; calibrationAngle = a[motor] * x + b[motor]; servoWrite(motorPin , calibrationAngle); rawAngle , motorPin = motorInfo(motor); if ((i % 3) == 0) { yi[k+1] = x; xi[k] = rawAngle; Serial.print(" | | Real ang: "); Serial.print(x); Serial.print(" -> Servo ang: "); Serial.print(calibrationAngle); Serial.print(" Enc: "); Serial.println(rawAngle); k++; } if (i >= stp) { swing = false; } i++; } } swing = true; i = 0; while (swing == true) { // moving unsigned long currentMicros = micros(); if (currentMicros - previousMicros >= 10000) { // save the last time you blinked the LED previousMicros = currentMicros; x = x2[motor] + float(i) * (x1[motor] - x2[motor]) / stp; calibrationAngle = a[motor] * x + b[motor]; servoWrite(motorPin , calibrationAngle); rawAngle , motorPin = motorInfo(motor); if ((i % 6) == 0) { yi[k+1] = x; xi[k] = rawAngle; Serial.print(" | | Real ang: "); Serial.print(x); Serial.print(" -> Servo ang: "); Serial.print(calibrationAngle); Serial.print(" Enc: "); Serial.println(rawAngle); k++; } if (i >= stp) { swing = false; } i++; } } swing = true; i = 0; while (swing == true) { // SECOND unsigned long currentMicros = micros(); if (currentMicros - previousMicros >= 10000) { // save the last time you blinked the LED previousMicros = currentMicros; x = x1[motor]; calibrationAngle = a[motor] * x + b[motor]; servoWrite(motorPin , calibrationAngle); rawAngle , motorPin = motorInfo(motor); if ((i % 3) == 0) { yi[k+1] = x; xi[k] = rawAngle; Serial.print(" | | Real ang: "); Serial.print(x); Serial.print(" -> Servo ang: "); Serial.print(calibrationAngle); Serial.print(" Enc: "); Serial.println(rawAngle); k++; } if (i >= stp) { swing = false; } i++; } } Serial.println(" | | Interpolation finished!"); /*-------Calculate linear interpolation of the encoder from 60 meassures done in swing------*/ double sx = 0; double sy = 0; double sx2 = 0; double sy2 = 0; double sxy = 0; double xmean = 0; double ymean = 0; int n = 300; for (int i = 0 ; i < n ; i++) { sx += xi[i+10]; sy += yi[i+10]; sx2 += xi[i+10] * xi[i+10]; sy2 += yi[i+10] * yi[i+10]; sxy += xi[i+10] * yi[i+10]; } ae[motor] = (n * sxy - sx * sy) / (n * sx2 - sx * sx); //sxy / sx2; // be[motor] = (sy - ae[motor] * sx) / n; //ymean - ae[motor] * xmean; Serial.println(" | | Moving back to ZERO position."); // turn the motor back to middle position swing = true; i = 0; while (swing == true) { unsigned long currentMicros = micros(); if (currentMicros - previousMicros >= 10000) { // save the last time you blinked the LED previousMicros = currentMicros; x = x1[motor] + float(i) * (90 - x1[motor]) / 60; calibrationAngle = a[motor] * x + b[motor]; servoWrite(motorPin , calibrationAngle); rawAngle , motorPin = motorInfo(motor); eang = ae[motor] * rawAngle + be[motor]; if ((i % 4) == 0) { Serial.print(" | | Servo ang: "); Serial.print(calibrationAngle); Serial.print(" -> Real ang: "); Serial.print(x); Serial.print(" -> Encoder ang: "); Serial.println(eang); } if (i >= 60) { swing = false; } i++; } } Serial.println("___|___|"); Serial.println(" | "); Serial.println("___"); Serial.println(" | Calibration finished satisfactory. Results data:"); Serial.print(" | HIGH lim: "); Serial.print(highLim[motor]); Serial.print(" LOW lim: "); Serial.println(lowLim[motor]); Serial.print(" | angle 1: "); Serial.print(ang1[motor]); Serial.print(" angle 2 "); Serial.println(ang2[motor]); Serial.print(" | Regression Motor a: "); Serial.print(a[motor], 5); Serial.print(" b: "); Serial.println(b[motor], 5); Serial.print(" | Regression Encoder a: "); Serial.print(ae[motor], 5); Serial.print(" b: "); Serial.println(be[motor], 5); Serial.println(" |"); Serial.println(" | ______________________________________________________________"); Serial.println(" | | |"); Serial.println(" | | This code won"t be able to save the updated parameters |"); Serial.println(" | | once the robot is shutted down. |"); Serial.println(" | | |"); Serial.println(" | | Please, write down the results |"); Serial.println(" | | and save them in the definition of each variable. |"); Serial.println(" | |_____________________________________________________________|"); Serial.println(" |"); Serial.println("___|"); Serial.println(" Select another motor."); Serial.print("SELECTED MOTOR: "); Serial.print(motorTag[motor]); Serial.print(". SELECTED RESOLUTION: "); Serial.println(res); } interp = false; secuence = false; } } SAFE = false; Serial.println("Calibration killed"); } // END OF CALIBRATION

build a homemade diy tft lcd driver breakout board pcb manufacturer

This website is using a security service to protect itself from online attacks. The action you just performed triggered the security solution. There are several actions that could trigger this block including submitting a certain word or phrase, a SQL command or malformed data.

build a homemade diy tft lcd driver breakout board pcb manufacturer

If you’ve been hanging around microcontrollers and electronics for a while, you’re surely familiar with the concept of the breakout board. Instead of straining to connect wires and components to ever-shrinking ICs and MCUs, a breakout board makes it easier to interface with the device by essentially making it bigger. The Arduino itself, arguably, is a breakout board of sorts. It takes the ATmega chip, adds the hardware necessary to get it talking to a computer over USB, and brings all the GPIO pins out with easy to manage header pins.

But what if you wanted an even bigger breakout board for the ATmega? Something that really had some leg room. Well, say no more, as [Nick Poole] has you covered with his insane RedBoard Pro Micro-ATX. Combining an ATmega32u4 microcontroller with standard desktop PC hardware is just as ridiculous as you’d hope, but surprisingly does offer a couple tangible benefits.

The RedBoard is a fully compliant micro-ATX board, and will fit in pretty much any PC case you may have laying around in the junk pile. Everything from the stand-off placement to the alignment of the expansion card slots have been designed so it can drop right into the case of your choice.

That’s right, expansion slots. It’s not using PCI, but it does have a variation of the standard Arduino “shield” concept using 28 pin edge connectors. There’s a rear I/O panel with a USB port and ISP header, and you can even add water cooling if you really want (the board supports standard LGA 1151 socket cooling accessories).

While blowing an Arduino up to ATX size isn’t exactly practical, the RedBoard is not without legitimate advantages. Specifically, the vast amount of free space on the PCB allowed [Nick] to add 2Mbits of storage. There was even some consideration to making removable banks of “RAM” with EEPROM chips, but you’ve got to draw the line somewhere. The RedBoard also supports standard ATX power supplies, which will give you plenty of juice for add-on hardware that may be populating the expansion slots.

build a homemade diy tft lcd driver breakout board pcb manufacturer

I found the TFT screen and Uno on Banggood.com about a month ago and over the weekend I was messing with the pair and found the tftbmp draw code in the demo.. I extended it with the ability to read any bmp file on the SD card.. so all you do is put your bitmaps on the SD and plug it in.. Having to add/edit/recompile/reload the Uno everytime is BS... Here is my code:

build a homemade diy tft lcd driver breakout board pcb manufacturer

This breakout board is designed to work in conjunction with our TFT displays to give you a faster, more flexible development process. This development tool will jumpstart your workflow by providing an all-in-one solution to run your hardware application and act as an intermediate PCB. With a compact design that allows for easy placement in your application, breakout boards make it easier than ever to connect with any MCU and see your design in action. This particular breakout board has a 40-pin FFC connector, 2.54mm pitch, and is breadboard friendly. It has a configurable LED driver with PWM, a power LED indicator, and open-source hardware.

Adjust the length, position, and pinout of your cables or add additional connectors. Get a cable solution that’s precisely designed to make your connections streamlined and secure.

Choose from a wide selection of interface options or talk to our experts to select the best one for your project. We can incorporate HDMI, USB, SPI, VGA and more into your display to achieve your design goals.

build a homemade diy tft lcd driver breakout board pcb manufacturer

In illustrated steps he connects the RIoTboard up to a Thin Film Transistor (TFT) LCD display, covers such things as the RIoTboard LVDS interface, board pin outs and selecting an In-Plane Switching panel, and solders the display to the breakout board…

The circuit at the heart of the system manages two power supplies: one to drive the panel, and another for the backlight (the two voltages will vary depending on the panel chosen). He writes:

The circuit has lots of ‘do not fit’ resistor locations that can be experimented with if it is desired to run the entire circuit and the RIoTboard from a single supply source.

Shabaz acknowledges that there are pre-built displays you could use with for the RIoTboard, but a “build-it-yourself” approach is more in the spirit of Gadget Master!

There are loads of details, step by step guides, lots of pics, the full circuit diagram, a parts list with order codes and plot (Gerber) files for the PCB…

build a homemade diy tft lcd driver breakout board pcb manufacturer

I"d been thinking about designing a project based on the Raspberry Pi RP2040, and to get more familiar with it I decided to try building a minimal RP2040-based computer on a prototyping board.

The RP2040 is a dual-core Arm Cortex-M0+ running at up to 133MHz, with 264 Kbytes of on-chip RAM, and support for up to 16 Mbytes of off-chip flash memory via a QSPI bus. It was designed in Cambridge, UK, by the team behind the Raspberry Pi boards, and is fabricated by TSMC using their 40nm process

My initial idea was to mount the RP2040 on a breakout board, bringing all the contacts to two rows of 28-way headers, and then mount all the other components on the prototyping board as I did with my earlier projects such as Minimal ATSAMD21 Computer and Minimal ATmega4809 on a Breadboard. However the only QFN56 breakout boards I could find arrange the pins in a square, making them unsuitable for a prototyping board.

I therefore started designing my own breakout board in Eagle. I soon realised that I could reduce the number of header pins by interconnecting the supply lines, and including the decoupling capacitors on the board. The hardware design datasheet

The board grew from a simple breakout board to something similar to the Raspberry Pi Pico, so you might wonder why I bothered to design it rather than just buy a Pico. The answer is that I wanted the experience of building my own board, and I wanted a board on which I could easily try out different components, such as different flash chips.

Unlike many other processors the RP2040 doesn"t include flash on chip, but includes a QSPI flash interface to make it easy to interface an external flash chip. I used the recommended part, the Winbond W25Q128JVS, which provides 16Mbytes, the largest amount of flash that the RP2040 will support. You can use any compatible flash chip up to 16Mbytes; see the hardware design datasheet for information about choosing a different flash chip.

Most of the passive components are 0402 size. This is smaller than I usually use so I was a bit apprehensive about working with them, but it wasn"t too difficult. I was also amazed at how cheap these components are; I got a pack of 50 100nF capacitors for 15 pence

For the other components I avoided the smallest package sizes, and chose the versions that are most widely available. The flash memory chip is SOIC, the 3.3V regulator is SOT23-5, and the crystal is 5x3.2mm.

There"s a good discussion in the RP2040 hardware design datasheet of how to calculate the crystal capacitors from the crystal"s load capacitance. The crystal I chose specifies a load capacitance of 12pF, and using their calculation the crystal capacitors should be 14pF; the values I used, 12pF, are close enough to this (it"s a coincidence that this is the same as the load capacitance).

None of the component values are particularly critical, and most of them could be ±10%, apart from the crystal capacitors which should probably be ±5%. The parts in the following parts list are just suggestions.

Unlike on the Raspberry Pi Pico, the pin legends are on the top of the board. The numbers correspond to the pin number in the I/O port, which is the same as the Arduino pin number. They are all in sequence, apart from 28 and 29 which are swapped as that"s the only way I could manage the PCB layout. The USB connections are in the same order as on a USB breakout board, so you can plug one onto a prototyping board alongside the appropriate pins.

All the main components are on the top of the board, apart from the decoupling components which are on the bottom of the board to make the PCB layout simpler. The tracks and spacings are 7mil, so you should be able to get it fabricated with the cheapest PCB option.

The RP2040 is only available in one package size, QFN56, and I think it"s safe to say that this makes the board impossible to solder with a conventional soldering iron. You"ll either need a hot air gun, or a reflow oven. I used a Youyue 858D+ hot air gun set to 275°C. You"ll also need a magnifying glass for examining the board.

Inevitably there may be some solder bridges between some of the package pins, and I used a conventional soldering iron with a fine tip to remove these. I avoid using solder braid as I find that this scratches the PCB; instead I stripped a short section of insulation from a fine stranded cable, dipped it in flux, and then used this to soak up the excess solder on each solder bridge.

As this was the first time I"d worked with 0402 components I found it a bit of a challenge. When picking them up with the tweezers it"s easy to accidentally flick them across the room, and they also tend to blow away if you get the hot air gun too close! I recommend ordering a few spares in case this happens.

With a continuity tester check between adjacent RP2040 pins to ensure that you haven"t missed any solder bridges. I used my Continuity Tester. Most of the pins come to header pins, making this relatively easy.

The next step is to fit headers to the Minimal RP2040 Board, fit it on a prototyping board with a USB connection and an LED, and try running the Blink example program.

I recommend Earle Philhower’s Raspberry PiRP2040 Boards core which supports a wide range of RP2040 boards, supports more Serial, SPI, and I2C ports, and gives significantly better performance than the Arduino RP2040 core. For instructions on how to install it see: https://github.com/earlephilhower/arduino-pico.

Set Flash Size to the appropriate option for the SPI Flash chip you"ve used. If like me you used a 128Mbit chip choose the 16MB option, and choose the one with FS to allocate space for use by LittleFS.

build a homemade diy tft lcd driver breakout board pcb manufacturer

Our PCBs are precision manufactured and undergo automatic optical inspection, human visual inspection and flying probe electrical testing to ensure every circuit board is just as ordered. We’ve long been the trusted partner of engineers, inventors, small businesses, and Fortune 500 companies.

build a homemade diy tft lcd driver breakout board pcb manufacturer

In tutorial we will learn how to build a DIY Arduino RC transmitter. Very often I need wireless control for the projects that I make, so therefore I built this multifunctional radio controller which can be used for pretty much everything.

Now I can wirelessly control any Arduino project with just some small adjustments at the receiver side. This transmitter can be also used as any commercial RC transmitter for controlling RC toys, cars, drones and so on. For that purpose it just needs a simple Arduino receiver which then generates the appropriate signals for controlling those commercial RC devices.

I will explain how everything works in this video through few examples of controlling an Arduino robot car, controlling the Arduino Ant Robot from my previous video and controlling a brushless DC motor using an ESC and some servo motors.

The radio communication of this controller is based on the NRF24L01 transceiver module which if used with an amplified antenna it can have a stable range of up to 700 meters in open space. It features 14 channels, 6 of which are analog inputs and 8 digital inputs.

It has two joysticks, two potentiometers, two toggle switches, six buttons and additionally an internal measuring unit consisting of an accelerometer and a gyroscope which can be also used for controlling things with just moving around or tilting the controller.

To begin with, let’s take a look at the circuit diagram. The brain of this RC controller is an Arduino Pro Mini which is powered using 2 LiPo batteries producing around 7.4 volts. We can connect them directly to the RAW pin of the Pro Mini which has a voltage regulator that reduced the voltage to 5V. Note that there are two versions of the Arduino Pro Mini, like the one I have that operates at 5V and the other operates at 3.3V.

On the other hand, the NRF24L01 module strictly needs 3.3V and it’s recommended to come from a dedicated source. Therefore we need to use a 3.3V voltage regulator which is connected to the batteries and convert the 7.4V to 3.3V. Also we need to use a decoupling capacitor right next to the module in order to keep the voltage more stable, thus the radio communication will be more stable as well. The NRF24L01 module communicates with the Arduino using SPI protocol, while the MPU6050 accelerometer and gyro module uses the I2C protocol.

I actually ended up utilizing all analog and digital pins of the Arduino Pro Mini. So now if I try to connect everything together using jump wires it will be quite a mess. Therefore I designed a custom PCB using the EasyEDA free online circuit design software.

Here I took into consideration the ergonomics of the controller and designed it to be easily held by two hands, while all controls are within the range of the fingers. I made the edges round and added some 3mm holes so I can mount the PCB onto something later. I placed the pins for programming the Arduino Pro Mini at the top side of the controller so they can be easily accessed in case we want to reprogram the Arduino. We can also notice here that I used the RX and TX pins of the Arduino for the joystick buttons. However these two lines needs to be disconnected from anything while we are uploading the sketch to the Arduino. So therefore they are interrupted with two pins which can be then easily connected using simple jumper caps.

Please note: Make sure you have the right Arduino Pro Mini version to mach the PCB or modify the PCB design according to it. Here’s a comparison photo between the three different versions, depending on your Arduino and the voltage regulator.

Here we can simply drag and drop the Gerber file and once uploaded, we can review our PCB in the Gerber viewer. If everything is all right then we can go on and select the properties that we want for our PCB. This time I chose the PCB color to be black. And that’s it, now we can simply order our PCB at a reasonable price. Note that if it’s your first order from JLCPCB, you can get up to 10 PCBs for only $2.

And here it is. I just really love how this PCB turned out in this black color. The quality of the PCB is great, and everything is exactly the same as in the design.

Ok now we can move on with assembling the PCB. I started with a soldering the pin headers of the Arduino Pro Mini. An easy and good way to do that is to place them onto a breadboard and so they will stay firmly in place while soldering.

For the particular model that I have, I need 5 pins for each side, while leaving one GND pin empty because I used its area below on the PCB for running some traces. I soldered the Arduino Pro Mini directly onto the PCB and cut the execs length of the headers. Right next to it goes the MPU6050 accelerometer and gyroscope module.

Then I soldered the 3.3V voltage regulator with a capacitor next to it, and another capacitor near the NRF24L01 module. This module have three different versions and we can use any of them here.

We can note here that I previously cut the length of the knobs so I can properly fit some caps onto them. However, we will solder the potentiometers to the PCB a bit later.

Finally what’s left is to solder the four push buttons. However they don’t have the proper height, so again I used pin headers to extend their pins a little bit.

And that’s it, our PCB is now ready so we can continue with making the cover for it. Because I like how the PCB looks and I want to be visible I decided to use transparent acrylic for the cover.

Here I have 4 mm tick transparent acrylic which currently have a protective foil and appears to be blue. The idea for the cover is to make two plates with the shape of the PCB and secure one of them at the top side and the other at the bottom side of the PCB.

Next I marked the locations where I need to make openings for the components to pass through. Using a 3mm drill I first made the 4 holes for securing the plates to the PCB. For these holes I also made counter sinks so that the bolts can be placed flash with the plates.

For the openings for the toggle switches and the potentiometers I used 6mm drill, and for the joystick openings I used 25mm Forstner bit. Again, using a rasp, I fine-tuned all the openings.

Before assembling the cover, just a quite note that I actually soldered the pin header for the power supply upside down so it can be reached from the back side where the battery will be located.

Ok now we can start with assembling the cover. I started with peeling off the protective foil from the acrylic which I must admit was quite satisfying because the acrylic was so clean now. So first I secured the two potentiometers on the top plate, inserted the 3mm mounting bolts and placed the 11mm distance rings in place.

Then I carefully merged and secured the top plate and the PCB using some bolts. At this point I finally soldered the potentiometers to the PCB because earlier I didn’t know exactly at what height they will be placed.

Next on the back plate I attached the battery holder using 2 bolts. I finished the cover assembly by securing the back plate to the back side of the PCB using the four mounting bolts.

Finally, we can attach the battery lines to the power supply pins, insert and secure the knobs on the potentiometers, insert the joysticks knobs and attach the antenna to the NRF24l01 module. And that’s it, we are finally done with the DIY Arduino RC transmitter.

What’s left now is to program the Arduino. For programming a Pro Mini board we need an USB to serial UART interface which can be hooked up to the programing header located on the top side of our controller.

Then in the Arduino IDE tools menu we need to select the Arduino Pro or Pro Mini board, select the proper version of the processor, select the port and select the programming method to “USBasp”.

Let’s explain how the transmitter code works. So first we need to include the SPI and RF24 library for the wireless communication, and the I2C library for the accelerometer module.  Then we need to define the digital inputs, some variables needed for the program below, define the radio object and the communication address.

Then we need to define a structure where we will store the 14 input values of the controller. The maximum size of this structure can be 32 bytes because that’s the NRF24L01 buffer limit or the amount of data the module can send at once.

In the setup section we need to initialize the MPU6050 module and we can also calculate the IMU error which is a values that is later used when calculating the correct angles of the module.

Then we need to initialize the radio communication, activate the Arduino internal pull-up resistors for all digital inputs and set the initial default values for all variables.

In the loop section start by reading the all analog inputs, map their values from 0 to 1023 into byte values from 0 to 255 because we already defined the variables in our structure as bytes. Each input is stored in the particular data variable from the structure.

So instead of the joystick 1 X and Y values we are using the angle values we are getting from the IMU, which we previously convert them from values from -90 to +90 degrees into byte values from 0 to 255 appropriately.

data.j1PotX = 127; // Values from 0 to 255. When Joystick is in resting position, the value is in the middle, or 127. We actually map the pot value from 0 to 1023 to 0 to 255 because that"s one BYTE value

// We can call this funtion in the setup section to calculate the accelerometer and gury data error. From here we will get the error values used in the above equations printed on the Serial Monitor.

accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) + 1.15; // AccErrorX ~(-1.15) See the calculate_IMU_error()custom function for more details

Now let’s take a look at how we can receive this data. Here’s a simple Arduino and NRF24L01 receiver schematic. Of course you can use any other Arduino board.

And here’s a simple receiver code where we will receive the data and simply print it on the serial monitor so that we know that the communication works properly. Again we need to include the RF24 library and define the objects and the structure the same way as in the transmitter code. In the setup section when defining the radio communication we need to use the same settings as the transmitter and set the module as receiver using the radio.startListening() function.

if ( currentTime - lastReceiveTime > 1000 ) { // If current time is more then 1 second since we have recived the last data, that means we have lost connection

resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone has a throttle up and we lose connection, it can keep flying unless we reset the values

In the main loop using the available() function we check whether there is an incoming data. If true we simply read the data and store it into the variables of the structure. Now we can print the data on the serial monitor to check whether the transmission work properly. Also using the millis() function and an if statement we check whether we keep receiving data, or if we don’t receive data for a period longer than 1 second, then we reset variables to their default values. We use this to prevent unwanted behavior, for example if a drone has a throttle up and we lose connection it can keep flying away unless we reset the values.

So that’s it. Now we can implement this method of receiving the data for any Arduino project. For example here the code for controlling the Arduino robot car from one of my previous videos.

As an update to this project, I made a dedicated Arduino based RC Receiver. Again, it’s based on the Arduino Pro mini board and it has several ready to use servos and ESCs connections, placed on a compact PCB.

Here we need to define the libraries, the structure and the radio communication as explained earlier. Then in the main loop we just need read the incoming data and use any of it for whatever we want. In this case I use the joystick 1 values for driving the car.

In the exact same way I made the Arduino Ant Robot from my previous video to be wirelessly controlled using this Arduino RC Transmitter. We just need to read the data, and according to it execute the appropriate functions, like moving forward, left, right, bite, attack and so on.

Usually for these devices we need to control their servos or brushless motors. So after receiving the data from the transmitter, for controlling servo we simply use the Arduino Servo library and use values from 0 to 180 degrees. For controlling brushless motor using ESC, we can again use the servo library for generating the 50Hz PWM signal used for controlling the ESC. By varying the duty cycle from 1000 to 2000 microseconds we control the RPM of the motor from zero to maximum. However, more on controlling brushless motors using ESC in my next tutorial.

Please note that we actually cannot bind the standard RC receiver system with this NRF24L01 2.4GHz system. Instead, we need to modify or create our own receiver consisting of an Arduino and NRF24L01 Module. From there we can than generate the appropriate PWM or PPM signals for controlling the RC device.

if ( currentTime - lastReceiveTime > 1000 ) { // If current time is more then 1 second since we have recived the last data, that means we have lost connection

resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone jas a throttle up, if we lose connection it can keep flying away if we dont reset the function

So that’s it. I hope you enjoyed this video and learned something new. Feel free to ask any question in the comments section below and check my Arduino Projects Collection.

build a homemade diy tft lcd driver breakout board pcb manufacturer

Hi guys, welcome to today’s tutorial. Today, we will look on how to use the 1.8″ ST7735  colored TFT display with Arduino. The past few tutorials have been focused on how to use the Nokia 5110 LCD display extensively but there will be a time when we will need to use a colored display or something bigger with additional features, that’s where the 1.8″ ST7735 TFT display comes in.

The ST7735 TFT display is a 1.8″ display with a resolution of 128×160 pixels and can display a wide range of colors ( full 18-bit color, 262,144 shades!). The display uses the SPI protocol for communication and has its own pixel-addressable frame buffer which means it can be used with all kinds of microcontroller and you only need 4 i/o pins. To complement the display, it also comes with an SD card slot on which colored bitmaps can be loaded and easily displayed on the screen.

The schematics for this project is fairly easy as the only thing we will be connecting to the Arduino is the display. Connect the display to the Arduino as shown in the schematics below.

Due to variation in display pin out from different manufacturers and for clarity, the pin connection between the Arduino and the TFT display is mapped out below:

We will use two libraries from Adafruit to help us easily communicate with the LCD. The libraries include the Adafruit GFX library which can be downloaded here and the Adafruit ST7735 Library which can be downloaded here.

We will use two example sketches to demonstrate the use of the ST7735 TFT display. The first example is the lightweight TFT Display text example sketch from the Adafruit TFT examples. It can be accessed by going to examples -> TFT -> Arduino -> TFTDisplaytext. This example displays the analog value of pin A0 on the display. It is one of the easiest examples that can be used to demonstrate the ability of this display.

The second example is the graphics test example from the more capable and heavier Adafruit ST7735 Arduino library. I will explain this particular example as it features the use of the display for diverse purposes including the display of text and “animated” graphics. With the Adafruit ST7735 library installed, this example can be accessed by going to examples -> Adafruit ST7735 library -> graphics test.

The first thing, as usual, is to include the libraries to be used after which we declare the pins on the Arduino to which our LCD pins are connected to. We also make a slight change to the code setting reset pin as pin 8 and DC pin as pin 9 to match our schematics.

Next, we create an object of the library with the pins to which the LCD is connected on the Arduino as parameters. There are two options for this, feel free to choose the most preferred.

Next, we move to the void setup function where we initialize the screen and call different test functions to display certain texts or images.  These functions can be edited to display what you want based on your project needs.

testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", ST7735_WHITE);

All the functions called under the void setup function, perform different functions, some draw lines, some, boxes and text with different font, color and size and they can all be edited to do what your project needs.

The complete code for this is available under the libraries example on the Arduino IDE. Don’t forget to change the DC and the RESET pin configuration in the code to match the schematics.

Uploading the code to the Arduino board brings a flash of different shapes and text with different colors on the display. I captured one and its shown in the image below.

That’s it for this tutorial guys, what interesting thing are you going to build with this display? Let’s get the conversation started. Feel free to reach me via the comment section if you have any questions as regards this project.

build a homemade diy tft lcd driver breakout board pcb manufacturer

I use LCD displays in almost every project. They are perfect for displaying data about voltage, current, time, frequency, wind speed, rainfall, etc. However, in this modern age of steampunk, I stumbled on something much cooler.

I found a number of vendors on eBay who were selling surplus 1” high seven-segment electromechanical displays (EMDs) that go clickity click (see Figure 1).

The segments appear and disappear in the blink of an eye when the tiny coils are pulsed. They aren’t quite as fast as LCDs, but they can add a whole new dimension to your project: sound!

Many months ago, I embarked on an ambitious project that featured five 1941 vintage rotary telephone step-by-step (SXS) switches. I thought these little EMDs would be the perfect match to display the dialed digits; refer to Figure 2. So, I ordered a dozen from a guy in Hungary and the rest is history. You can see nine of them mounted in a line under the SXS switches.

The displays didn’t come with drivers and I couldn’t find a commercial source. I saw a reference to a 40-pin FP2800A decoder/driver IC but it was no longer available, so I decided to build my own. Maybe I missed something, but it wouldn’t be the first time I set about reinventing the wheel.

I learned a few things along the way, and it was a rewarding experience to design and build the PCB (printed circuit board) drivers using tiny SMD components. Perhaps you can find an application for these funky little displays and have as much fun building with them as I did.

My requirements were simple. Each display had to be a stand-alone unit with its own driver. I needed them to be physically located at different positions in the telephone project, which didn’t lend itself to grouping them in most cases. So, I made each one an independe