Houpačka

Projekt "Houpačka" byl koncipován jako vzdělávací aktivita, jejímž cílem bylo zábavnou formou seznámit účastníky s principy fungování Arduino platformy, programováním a základy senzoriky. Žáci si prostřednictvím tohoto projektu osvojili dovednosti v oblasti měření vzdálenosti pomocí ultrazvukových senzorů, zpracování dat a tvorby jednoduchých aplikací. Současně projekt podporoval rozvoj kreativního myšlení a řešení problémů.

Cílem zařízení se dvěma ultrazvukovými senzory bylo následující: pokud se pohnulo s černou kostkou proti ultrazvukovému senzoru nebo naopak, tak servomotor nadzvedl nebo snížil dřevěnou rovinu a poslal vozíček na stejnou vzdálenost jakou představovala vzdálenost mezi ultrazvukovým senzorem a černou kostičkou.

Program pro arduino:

#include <Servo.h>
#define Umax 66 // degrees
#define Umin -66
#define Umax_rad 1.151 // radians
#define Umin_rad -1.151
#define T 0.09

const int echoPin2= 4; 
const int trigPin2= 3;
const int echoPin1= 6; 
const int trigPin1= 7; 

Servo servo;

double setpoint, setpoint_prec;  // In METRI : 30cm --> 0.3m
double y, y_prec;
double error;
double P, I, D, U;
double I_prec=0, U_prec=0, D_prec=0;        
boolean Saturation = false;

double Kp = 8.6; //
double Ki = 1.1; // 0.1
double Kd = 6.3;  // 
float measure_1 (void);
float measure_2 (void);
void move_servo(int);

void setup() {

   Serial.begin(9600);
   
   pinMode(trigPin2, OUTPUT);
   pinMode(echoPin2, INPUT);
   pinMode(trigPin1, OUTPUT);
   pinMode(echoPin1, INPUT);
   servo.attach(9);   
  
   delay(1000); 
   move_servo(90);
   delay(2000);
   setpoint_prec = measure_2();  // blocco
   delay(1000);
   y_prec = measure_1();  // carrello
   delay(1000);
   
}

void loop() {
   
   setpoint = measure_2();  // cube   // meters
   setpoint = 0.53*setpoint + 0.47*setpoint_prec; // digital filter
   
   delay(3);
   
   y = measure_1();  // cart   // meters     (  alfa*y :   if alfa increase, y less filteres  --> so the signal is dirty but fast )
   y =  0.53*y + 0.47*y_prec; // digital filter
  
   delay (3);
   
   error = round( 100*(y - setpoint) )*0.01;                 
   
   // PID control

   P = Kp*error;
   
   if ( ! Saturation )  I = I_prec + T*Ki*error;

   D = (Kd/T)*(y - y_prec);
   
   D = 0.56*D + 0.44*D_prec;    // filter D     (  alfa*D :   if alfa increase, D less filteres  --> so the signal is dirty but fast )
   
   U = P + I + round(100*D)*0.01 ;  // U in radians
   
   // saturate control action
   
   if ( U < Umin_rad)  {
                        U=Umin_rad; 
                        Saturation = true;
                       }
                   
   else if ( U > Umax_rad)  {
                             U=Umax_rad; 
                             Saturation = true;
                            }

   else     Saturation = false;                   
   
   U=round(U*180/M_PI);     // Transform U in degrees:   -63 < U° < 63   
          
   U=map(U, Umin, Umax, 24, 156); 
   
   if (U < 83 || U > 95 || abs(error) > 0.02 ) move_servo( round(U) );   // it is used to stop the servo when the setpoint is reached
   
   delay (24);  

   //Serial.print(setpoint*100);
   //Serial.print(" ");
   //Serial.print(y*100);
   //Serial.print(" ");
   //Serial.print(U);
   //Serial.println();
   
   I_prec = I;
   y_prec = y;
   D_prec = D;
   setpoint_prec = setpoint;     
}

float measure_1 (void) {

long elapsed_time=0;
float distance=0; 

digitalWrite(trigPin1, LOW); 
delayMicroseconds(10); 

digitalWrite(trigPin1, HIGH);
delayMicroseconds(10);
 
digitalWrite(trigPin1, LOW);

elapsed_time = pulseIn(echoPin1, HIGH);
distance = (float)elapsed_time/58.2;

delay(30);

if (distance > 42) distance=43;
else if (distance < 0) distance=0;

return 0.01*(distance-1.5+0.5);   // meters    

}

float measure_2 (void) {

long elapsed_time=0;
float distance=0; 

digitalWrite(trigPin2, LOW); 
delayMicroseconds(10); 

digitalWrite(trigPin2, HIGH);
delayMicroseconds(10);
 
digitalWrite(trigPin2, LOW);

elapsed_time = pulseIn(echoPin2, HIGH);
distance = (float)elapsed_time/58.2;

delay(30);

if (distance > 42) distance=43;
else if (distance < 0) distance=0;

return 0.01*(distance+2);   // meters    +2cm to get the center of the cube

} 

void move_servo(int u) {
  
servo.write(u-map(u, 30, 150, 14, 3));
   
}

Další podobné články

Test ESC a BLDC motoru

Cílem tohoto Arduino projektu je testování a kalibrace obousměrného regulátoru otáček (ESC) pomocí PWM signálu. Program simuluje sekvenci pohybů: dopředu, neutrální pozici a reverzní chod, což umožňuje ověřit správnou funkci ESC včetně přepínání směru otáčení motoru.

Laserový alarm

Cílem tohoto projektu je vytvořit jednoduchý, ale funkční bezpečnostní systém, který detekuje narušení prostoru pomocí vysílače (laserového paprsku) a přijímače (fotorezistoru). Jakmile je paprsek přerušen, Arduino to vyhodnotí jako narušení a spustí alarm – například zvukový signál pomocí piezo bzučáku.