Introduction: Magic Ball ( PID Control, Arduino Due )
Breadboard to demonstrate PID control on the Arduino Due.
Supplies
1. Arduino Due x1
2. Touchscreen 5 wires x1
3. Power supply unit 5 V. x1
4. Servomotors x2
5. Plywood 6 and 8 mm.
Layout created in Autodesk Fusion 360 and CorelDraw 2021.
Step 1: Making the Platform
We cut out the details with a laser cutter.
Then we put the parts together and glue them with wood glue.
Step 2: Download the Program to the Arduino Due.
#include <Servo.h> #include <PID_v1.h> // Specify links and initial settings double Kp = 4, Ki = 1, Kd = 2; // Define the variables we will connect to double Setpoint_X, Input_X, Output_X; double Setpoint_Y, Input_Y, Output_Y; PID myPID_X(&Input_X, &Output_X, &Setpoint_X, Kp, Ki, Kd, DIRECT); PID myPID_Y(&Input_Y, &Output_Y, &Setpoint_Y, Kp, Ki, Kd, DIRECT); int Target_x, Target_y; int Delta_x, Delta_y; const int servo1 = 8; // servo motor X const int servo2 = 9; // servo motor Y Servo myservo1; // create a Servo object to control servo motor X Servo myservo2; // create a Servo object to control servo motor Y // NEC touch screen const byte PS = 0; // PS touchscreen output const byte UL = 3; // UL touchscreen output const byte UR = 4; // UR touchscreen output const byte LL = 5; // LL touchscreen output const byte LR = 6; // LR touchscreen output int TouchScreenVal_x; // variable for storing data from analog pin X int TouchScreenVal_y; // variable for storing data from analog pin Y int TouchScreenVal_xm; // variable to store data for servo motor X int TouchScreenVal_ym; // variable to store data for servo motor Y int TouchScreenVal_x0; // variable to store the starting point X0 int TouchScreenVal_y0; // variable to store the starting point Y0 int servoVal_xm; // variable for storing data from servo motor X int servoVal_ym; // variable for storing data from servo motor Y int servoVal_x0; // variable for storing data X0 int servoVal_y0; // variable for storing data Y0 void setup () { // Setting up the touchscreen pinMode (PS, INPUT); pinMode (UR, OUTPUT); pinMode (UL, OUTPUT); pinMode (LL, OUTPUT); pinMode (LR, OUTPUT); digitalWrite (UL, LOW); // UL digitalWrite (UR, LOW); // UR digitalWrite (LL, LOW); // LL digitalWrite (LR, LOW); // LR // Initialize the serial communication protocol Serial.begin (9600); // ADC analogReadResolution (12); // Servo myservo1.attach (servo1); // connect servo motor X myservo2.attach (servo2); // connect servo motor Y // enable PID myPID_X.SetMode (AUTOMATIC); myPID_Y.SetMode (AUTOMATIC); TouchScreenVal_x0 = 0; TouchScreenVal_y0 = 0; servoVal_x0 = 107; servoVal_y0 = 104; Target_x = 512; Target_y = 360; } void loop () { digitalWrite (UR, HIGH); // UR digitalWrite (LL, LOW); // LR // read the X value from the touchscreen along the horizontal axis (values between 1000 and 3000) digitalWrite (UL, LOW); // UL digitalWrite (LR, HIGH); // LL delayMicroseconds (200); // delay (1); TouchScreenVal_x = analogRead (PS); TouchScreenVal_xm = TouchScreenVal_x0; if (TouchScreenVal_x> 100) TouchScreenVal_xm = TouchScreenVal_x0 + map (TouchScreenVal_x, 1330, 2570, 0, 1023); // scale the resulting value for use with a servo motor (range: 100 to 110) // read the Y value from the touchscreen along the vertical axis (value from 1000 to 3000) digitalWrite (UL, HIGH); // UL digitalWrite (LR, LOW); // LL delayMicroseconds (200); // delay (1); TouchScreenVal_y = analogRead (PS); TouchScreenVal_ym = TouchScreenVal_y0; if (TouchScreenVal_y> 100) TouchScreenVal_ym = TouchScreenVal_y0 + map (TouchScreenVal_y, 1330, 2680, 0, 767); // scale the resulting value for use with a servo motor (range: 100 to 110) Setpoint_X = Target_x; Input_X = TouchScreenVal_xm; myPID_X.Compute (); servoVal_xm = servoVal_x0 + map (Output_X, 0, 255, +4, -4); // scale the resulting value for use with the servo motor (result in the range 99 to 109) myservo1.write (servoVal_xm); // display the rotor of the second servo motor in accordance with the obtained scale level Delta_x = Target_x - TouchScreenVal_xm; Setpoint_Y = Target_y; Input_Y = TouchScreenVal_ym; myPID_Y.Compute (); servoVal_ym = servoVal_y0 + map (Output_Y, 0, 255, -4, +4); // scale the resulting value for use with the servo motor (result in the range 99 to 109) myservo2.write (servoVal_ym); // display the rotor of the second servo motor in accordance with the obtained scale level Delta_y = Target_y - TouchScreenVal_ym; //OutputPID (); } // display PID values void OutputPID () { Serial.print ("SX ="); Serial.print (Setpoint_X); //Serial.print ("TX ="); Serial.print(TouchScreenVal_x); Serial.print ("MX ="); Serial.print (TouchScreenVal_xm); Serial.print ("DX ="); Serial.print (Delta_x); Serial.print ("OX ="); Serial.print (Output_X); Serial.print ("SMX ="); Serial.print (servoVal_xm); Serial.print ("---"); Serial.print ("SY ="); Serial.print (Setpoint_Y); //Serial.print ("TY ="); Serial.print(TouchScreenVal_y); Serial.print ("MY ="); Serial.print (TouchScreenVal_ym); Serial.print ("DY ="); Serial.print (Delta_y); Serial.print ("OY ="); Serial.print (Output_Y); Serial.print ("SMY ="); Serial.print (servoVal_ym); Serial.println ("!"); }