diff --git a/README.md b/README.md index 2b82f67..49bc152 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Sistemas possíveis: - 1 - [Maglev](/simulacao_maglev/README.md) - 2 - [Pêndulo invertido](/simulacao_pendulo_invertido/README.md) - 3 - pêndulo de múltiplos estágios -- 4 - [Aeropêndulo](/simulacao_modelagem_aeropendulo/README.md) +- 4 - [Aeropêndulo](/simulacao_modelagem_aeropendulo/aeropendulo_doc.html) - 5 - [Motor DC](/simulacao_motor_dc/README.md) - 5 - Massa mola (múltiplas massas) - 6 - suspensão de veículo @@ -33,4 +33,4 @@ Sistemas possíveis: - 8 - ball plate - 9 - drone (precisa mais informação) - 10 - Motor DC ou Indução - + \ No newline at end of file diff --git a/simulacao_modelagem_aeropendulo/Modelagem_matematica_do_aeropendulo.ipynb b/simulacao_modelagem_aeropendulo/Modelagem_matematica_do_aeropendulo.ipynb index ecb6334..a25667b 100644 --- a/simulacao_modelagem_aeropendulo/Modelagem_matematica_do_aeropendulo.ipynb +++ b/simulacao_modelagem_aeropendulo/Modelagem_matematica_do_aeropendulo.ipynb @@ -5,7 +5,38 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#
Modelagem e Simulação do Aeropêndulo
" + "\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "Universidade Federal do Pará\\\n", + "Campus Universitário de Tucuruí\\\n", + "Faculdade de Engenharia Elétrica\n", + "\n", + "Orientador: Raphael Teixeira\\\n", + "Autor: Oséias Farias" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#
Modelagem e Simulação Aeropêndulo
" ] }, { @@ -15,8 +46,8 @@ "source": [ "
\n", "
\n", - " \n", + " \n", "

Figura 1 - Diagrama esquemático do Aeropêndulo.

\n", "
\n", "
" @@ -27,23 +58,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Usando as leis de Newton e momentos angulares podemos encontrar o modelo matemático que descreve a dinâmica do aeropêndulo, assim, temos a equação $(1)$ que modela o sistema em questão.\n", - "\n", - "$$\n", - "\\begin{align}\n", - " T &= J\\ddot{\\theta} + c\\dot{\\theta} +mgd\\sin{\\theta} \\tag{1}\\\\\n", - "\\end{align}\n", - "$$\n", - "\n", - "\n", - "Onde:\n", - "\n", - ">> + $T$: Empuxo gerado pela hélice;\n", - ">> + $J$: Momento de inércia;\n", - ">> + $\\theta$: posição angular do Aeropêndulo;\n", - ">> + $c$: coeficiente de amortecimento viscoso;\n", - ">> + $m$: peso do Aeropêndulo;\n", - ">> + $d$: a distância entre o centro de massa e o ponto de pivô;" + "Usando as leis de Newton e momentos angulares podemos encontrar o modelo matemático que descreve a dinâmica do aeropêndulo, assim, temos a equação $(1)$ que modela o sistema em questão." ] }, { @@ -51,7 +66,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Linearizando o sistema" + "$$\n", + "\\begin{align}\n", + " T &= J\\ddot{\\theta} + c\\dot{\\theta} +mgd\\sin{(\\theta)} \\tag{01}\\\\\n", + "\\end{align}\n", + "$$" ] }, { @@ -59,13 +78,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Uma das técnicas de linearização quando se tem sistemas não lineares que a componente não linear é o seno ou cosseno é considerar o seno ou cosseno sendo o valor do próprio ângulo, isso funciona bem para pequenas variações em torno do ângulo, aplicando essa técnica ao modelo do aeropêndulo, temos a equação $(2)$.\n", + "Queremos controlar o ângulo do braço do aeropêndulo a partir da tensão aplicada aos terminais do motor, assim,devemos encontrar uma relação entre a tensão $V$ nos terminais do motor e o empuxo $T$ gerado pela hélice, essa relação é não linear, porém é possível aproximar por uma relação linear, como mostra a expressão $(7)$.\n", "\n", "$$\n", "\\begin{align}\n", - " T &= J\\ddot{\\theta} + c\\dot{\\theta} +mgd\\theta \\tag{2}\\\\\n", + " T &\\approx K_mV \\tag{02} \\\\\n", + " K_mV &= J\\ddot{\\theta} + c\\dot{\\theta} +mgd\\sin{(\\theta)} \\tag{03}\n", "\\end{align}\n", - "$$" + "$$\n", + "\n" ] }, { @@ -73,16 +94,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Aplicando a transformada de Laplace, temos:\n", - "\n", - "$$\n", - "\\begin{align}\n", - " T(s) &= s^2J\\theta(s) + sc\\theta(s) +mgd\\theta(s) \\tag{3}\\\\\n", - " T(s) &= (s^2J + sc +mgd)\\theta(s) \\tag{4}\\\\\n", - " \\frac{\\theta(s)}{T(s)} &= \\frac{1}{s^2J + sc +mgd} \\tag{5}\\\\\n", - " \\frac{\\theta(s)}{T(s)} &= \\frac{1/J}{s^2 + sc/J +mgd/J} \\tag{6}\\\\\n", - "\\end{align}\n", - "$$" + "
\n", + "
\n", + " \n", + "

Figura 2 - Diagrama de blocos do modelo do Aeropêndulo.

\n", + "
\n", + "
\n" ] }, { @@ -90,19 +108,53 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Queremos controlar o ângulo do braço do aeropêndulo a partir da tensão aplicada aos terminais do motor, assim,devemos encontrar uma relação entre a tensão $V$ nos terminais do motor e o empuxo $T$ gerado pela hélice, essa relação é não linear, porém é possível aproximar por uma relação linear, como mostra a expressão $(7)$.\n", "\n", "$$\n", "\\begin{align}\n", - " T &\\approx K_mV \\tag{7}\\\\\n", + " \\dot{x_2} &= x_1 \\tag{04} \\\\\n", + " \\dot{x_1}J &= - x_1c - mgdsen(x_2) + VK_m \\tag{05} \\\\\n", + " \\dot{x_1} &= \\dfrac{- x_1c - mgdsen(x_2) + VK_m}{J} \\tag{06}\n", "\\end{align}\n", "$$\n", + "\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Onde:\n", "\n", - "Aplicando a transformada de Laplace, temos:\n", + ">> + $T$: Empuxo gerado pela hélice;\n", + ">> + $J$: Momento de inércia;\n", + ">> + $\\theta$: posição angular do Aeropêndulo;\n", + ">> + $c$: coeficiente de amortecimento viscoso;\n", + ">> + $m$: peso do Aeropêndulo;\n", + ">> + $d$: a distância entre o centro de massa e o ponto de pivô;\n", + ">> + $V$: Tensão de Entrada do Motor CC Série\n", + ">> + $K_m$: Relação entre o torque e a tensão \n", + ">> + $x_1$ $e$ $x_2$: Estados do Sistema" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Linearizando o Aeropêndulo" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Uma das técnicas de linearização quando se tem sistemas não lineares que a componente não linear é o seno ou cosseno é considerar o seno ou cosseno sendo o valor do próprio ângulo, isso funciona bem para pequenas variações em torno do ângulo, aplicando essa técnica ao modelo do aeropêndulo, temos a equação $(2)$.\n", "\n", "$$\n", "\\begin{align}\n", - " T(s) &\\approx K_mV(s) \\tag{8}\\\\\n", + " K_mV &= J\\ddot{\\theta} + c\\dot{\\theta} +mgd\\theta \\tag{07}\\\\\n", "\\end{align}\n", "$$" ] @@ -112,14 +164,18 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Agora podemos substituir $(8)$ em $(6)$,\n", + "Aplicando a transformada de Laplace, temos:\n", "\n", "$$\n", "\\begin{align}\n", - " \\frac{\\theta(s)}{K_mV(s)} &= \\frac{1/J}{s^2 + sc/J +mgd/J} \\tag{9}\\\\\n", - " \\frac{\\theta(s)}{V(s)} &= \\frac{K_m/J}{s^2 + sc/J +mgd/J} \\tag{10}\n", + " K_mV(s) &= s^2J\\theta(s) + sc\\theta(s) +mgd\\theta(s) \\tag{08}\\\\\n", + " K_mV(s) &= (s^2J + sc +mgd)\\theta(s) \\tag{09}\\\\\n", + " \\frac{\\theta(s)}{K_mV(s)} &= \\frac{1}{s^2J + sc +mgd} \\tag{10}\\\\\n", + " \\frac{\\theta(s)}{K_mV(s)} &= \\frac{1/J}{s^2 + sc/J +mgd/J} \\tag{11}\\\\\n", + " \\frac{\\theta(s)}{V(s)} &= \\frac{K_m/J}{s^2 + sc/J +mgd/J} \\tag{12}\n", "\\end{align}\n", - "$$" + "$$\n", + "\n" ] }, { @@ -164,7 +220,7 @@ "\\begin{bmatrix}\n", " 0 \\\\\n", " \\frac{K_m}{J}\n", - "\\end{bmatrix}\\cdot u\n", + "\\end{bmatrix}\\cdot u \\tag{13}\n", "$$\n", "\n", "$$\n", @@ -174,7 +230,7 @@ "\\begin{bmatrix}\n", " 0 \\\\\n", " \\frac{K_m}{J}\n", - "\\end{bmatrix} + 0\n", + "\\end{bmatrix} + 0 \\tag{14}\n", "$$" ] }, @@ -216,7 +272,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ @@ -224,7 +280,9 @@ "import matplotlib.pyplot as plt\n", "import control as ct\n", "\n", - "plt.style.use(\"ggplot\")" + "plt.style.use(\"ggplot\")\n", + "\n", + "%config InlineBackend.figure_format = \"svg\"" ] }, { @@ -237,7 +295,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -259,7 +317,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ @@ -283,14 +341,14 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - ": sys[6]\n", + ": sys[21]\n", "Inputs (1): ['u[0]']\n", "Outputs (1): ['y[0]']\n", "States (2): ['x[0]', 'x[1]']\n", @@ -322,7 +380,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -334,7 +392,7 @@ "TransferFunction(array([2.79245283]), array([1. , 0.71698113, 9.98490566]))" ] }, - "execution_count": 24, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -354,7 +412,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 21, "metadata": {}, "outputs": [ { @@ -371,7 +429,7 @@ " 'SteadyStateValue': 0.2796674225245654}" ] }, - "execution_count": 25, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -382,7 +440,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 22, "metadata": {}, "outputs": [ { @@ -401,7 +459,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -410,7 +468,7 @@ "array([-0.35849057+3.13948884j, -0.35849057-3.13948884j])" ] }, - "execution_count": 27, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -421,7 +479,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 24, "metadata": {}, "outputs": [ { @@ -430,7 +488,7 @@ "array([], dtype=float64)" ] }, - "execution_count": 28, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -449,14 +507,1578 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 34, "metadata": {}, "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiQAAAFpCAYAAACs3TNfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABt2klEQVR4nO3dd3hUVfrA8e+d9F5II5RAgNB7U4o0FURAEREXC8qCBSysurorKuKCK+uiuOquuiKIuiiiKIigPykK0qUIhl6khIQEkhDSJ3N+f9zMkCGTMpmZTCa8n+fJk5k7t5yTmcm8c857ztGUUgohhBBCCDcyuLsAQgghhBASkAghhBDC7SQgEUIIIYTbSUAihBBCCLeTgEQIIYQQbicBiRBCCCHcTgISIYQQQridBCRCCCGEcDsJSIQQQgjhdhKQCFED27dvx8fHhyZNmpCVleXu4gghhMeTgEQIO+Xn53PPPfcwcuRIgoODmTp1aq1cd/369WiaxosvvujwuTRNY+DAgQ6fR1TPwIED0TTNapszn8/acuLECTRN47777nN3UUQ9JAGJcKrZs2ejaRqapnHw4EF3F8clnn76aQwGA4sWLeLLL79k+fLlLFmyxN3FEtWwcOFCy+vzuuuuq3C/EydOYDAYLPvWd6dOncLLywtN03j22WfdXZwq3XfffWiaxokTJ9xdFOFEEpAIp1FK8f7771v+gf/3v/91c4mcLycnh+joaL766iuCg4Np27YtX331FWlpae4umrCDt7c3GzZsqDBofv/991FK4e3tXcslc4/3338fk8mEpmksWLAAo9Ho7iKJq5AEJMJpvv/+e06cOMGECROIi4vjww8/pKioyN3FcqqQkBBeeOEFkpKSLNuGDBnCo48+6sZSCXuNGDEC0D+Ir1RSUsKCBQvo2bMnsbGxtV20WldSUsIHH3xAaGgoDz/8MKmpqSxfvtzdxRJXIQlIhNOYW0QmT57MXXfdRUZGBsuWLatw/9OnT/PII4+QmJiIn58fDRo0YNSoUWzfvr3cvi+++CKaprF+/Xr+97//0bt3b4KDg2nWrJlln7NnzzJ16lSaNWuGr68v0dHR3Hbbbfzyyy/lzmduul+4cCErV66kT58+BAUFERERwe23387hw4dtljkvL4+///3vdOnShaCgIIKDg7n22mtZvHhxuX3L5gjs3r2bm2++mfDwcAIDAxkwYACbNm2yeY20tDT++Mc/EhsbS0BAAF26dOHDDz+s8O/YrFkzq79DRX+36sjOzuavf/0rrVu3xt/fn4iICIYOHcoPP/xQrePLqunzu3jxYrp3705gYCDx8fE88cQTFBYWArB27VoGDhxIaGgoERER3HPPPZw/f97usrVv355rr72WDz/8kOLiYqvHVq5cSUpKCpMnT67w+IULFzJmzBgSExMJCAggNDSUvn378vHHH9tdFqDar4+UlBReeukl+vbtS1xcHL6+vsTHxzN+/HiSk5NrdO1Vq1Zx+vRpxo0bx8MPPwxUr3XzwIED3HrrrURGRhIUFES/fv34/vvvK9x/8eLFDBo0iPDwcPz9/Wnbti2zZs2yPLdlmXOcUlNTmTRpEo0aNcLLy8vyvjW/H5o3b27pViv7Hvjll194/PHH6dy5M5GRkfj7+9OqVSuefPJJMjMz7fwLiVqjhHCC1NRU5ePjo5KSkpRSSu3du1cBavDgwTb3/+WXX1SDBg2Upmlq2LBh6sknn1QTJkxQYWFhytfXV61cudJq/xkzZihAjRgxQvn5+anbb79dPfPMM+qhhx5SSil17NgxFR8fb7nmX/7yF3XXXXcpX19f5evrq1asWGF1vgULFihAjRw5Unl7e6uxY8eqv/71r+qmm25SgIqMjFQHDhywOiYzM1N17dpVAapbt27qkUceUVOmTFEtWrRQgJo+fbrV/uvWrVOAuvnmm1VAQIAaPHiwevLJJ9XYsWOVwWBQ/v7+5a6Rnp6uEhMTFaD69eun/vKXv6gJEyYof39/NWrUKAWoGTNmWB2TkJCgEhISbP6dzX+3devWWW0H1IABA8rVr127dgpQPXv2VM8884z64x//qEJCQpSmaeqdd96xeQ1bavr83nbbbSogIED94Q9/UE888YTq0KGDAtSECRPUl19+qXx9fdXo0aPVk08+qa699loFqGHDhlW7XObnffr06eqDDz5QgPr888+t9hkxYoQKDg5WOTk5qlGjRsrWv0l/f3/VvXt3NWHCBPWXv/xFTZ482bLvc889V27/AQMGlDtPTV4fixcvVgEBAWr48OFqypQp6umnn1ajR49WPj4+KigoSO3evbvafwuzkSNHKkD9/PPPSimlunfvrgwGgzpx4kS5fY8fP64Add1116nw8HDVv39/q9eowWBQn376abnj7r//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W6aqy/xF4rvvvqtw8rfVq1dz6tQpmjRpYrXd3vdN165d2blzp13lq+mEdDt27GDZsmVcf/31rFq1ymouGZPJxD/+8Y8anVe4ngQkwiHmuUa6d+9Oly5dbO6zfPlyfvjhB44fP07z5s255pprANiwYYNTPrC6du0KwMaNGzEajeUms1q3bh2gfxu+0o8//lhuW0lJCRs3brQ6d69evTAYDGzYsMHh8lakTZs2BAYGsnv3brKzs8t9+Fc0dDciIoJff/2V4uLicl1WO3bsqNa1W7duTWBgIHv27CErK6vct/bK/oZXcvbz62rmrsXTp09z7733VthiYXbkyBEAxowZU+4xW68nZ8nIyCArK4vbbrutXDBy6dIluz7wU1NT+eabbwgNDWXs2LE29zlw4AA///wzH3zwATNmzLB6bOfOneTk5JTrtjG/Rs3vm+DgYNq3b89vv/3GhQsXbHYH1oSXlxdAuRYkuPz8jBo1qtz/gm3btpXrXhN1h8xDIhxinq/g3//+N++//77NnwcffNAyiyvALbfcQosWLXj77bf59ttvbZ538+bN5OXlVasMjRs35oYbbuDEiRPl+qm3bt3K//73PyIiIhg9enS5Y9euXcs333xjte2tt97i6NGjDBo0iISEBABiYmK466672LFjB3/7299s/iM8evQox48fr1aZbfHx8eGuu+4iJyenXO7Fjh07+OSTT2we16tXL4xGIwsWLLDavnDhQn7++edqXdvX19dy7eeff97qsaNHj/Kvf/0LHx8f7rnnnirP5ezn19VCQkJYvXo1y5YtY9asWVXub57v4soA8bvvvrM50ZqzxMTEEBgYyC+//GLV3VVcXMzjjz9ORkZGtc/1wQcfYDQaueuuuyp835rn/Jg/f75V/gXoXTIvvfSS1TbzazQsLMzqvfbEE09QVFTExIkTbbbYZWZm2t160qBBA0DP5blSRc/PuXPnam3dKVEz0kIiamz9+vUcOnSIjh07VpoE+Mc//pHZs2ezYMECZs6ciY+PD19++SVDhw7l5ptvpk+fPnTp0oXAwEBOnTrF9u3bOXbsGGfPniUwMLBaZXnnnXfo27cvf/7zn/n+++/p0aMHp06d4vPPP8dgMLBgwQKbSXgjR45k9OjRjB49mpYtW7J7925WrVpFZGQk//73v632feuttzh8+DAvvPACH330Ef369SM2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fvttEhMTadmyJd9++y2FhYUMHDjQ3UUTQgghhB08OiDp06cPFy9eZMmSJWRlZdGsWTOeffZZm102QgghhKi7PDogARg2bBjDhg1zdzGEEEII4QCPzSERQgghRP0hAYkQQggh3E4CEiGEEEK4nQQkQgghhHA7CUiEEEII4XYeP8rGUd7ervkTuOq87lZf6wVSN08ldfNM9bVu9bVeYF03V9RTU/V1jlshhBBCeAzpsnGy/Px8nnnmGfLz891dFKeqr/UCqZunkrp5pvpat/paL6i9uklA4mRKKY4fP17vFleqr/UCqZunkrp5pvpat/paL6i9uklAIoQQQgi3k4BECCGEEG4nAYmT+fj4cPvtt+Pj4+PuojhVfa0XSN08ldTNM9XXutXXekHt1U1G2QghhBDC7aSFRAghhBBuJwGJEEIIIdxOAhIhhBBCuJ0EJEIIIYRwu/o76b6LrF69mhUrVpCVlUVCQgITJ06kZcuWFe6/efNmPvvsM9LT04mLi+Ouu+6iW7dutVjiqi1btoxt27Zx5swZfH19SUpK4u677yY+Pr7CY9avX8+///1vq20+Pj588sknri6uXZYsWcLSpUuttsXHxzNv3rwKj/GE5wxg6tSppKenl9t+4403MmnSpHLb6/JzlpyczPLlyzl+/DiZmZk89dRT9OrVy/K4UoolS5awZs0acnNzadOmDZMmTaJhw4aVntfe96srVFY3o9HIp59+yq5duzh37hyBgYF07NiR8ePHExkZWeE5a/K6doWqnre3336bH3/80eqYzp07M3369ErPW9efN4A77rjD5nF33303o0aNsvlYXXjeqvP/vqioiEWLFrFp0yaKi4vp3LkzkyZNIjw8vMLz1vQ9WpYEJHbYtGkTixYtYvLkybRq1YqVK1cye/Zs5s2bR1hYWLn9Dx48yBtvvMH48ePp1q0bGzdu5NVXX2XOnDk0bdrUDTWwLTk5maFDh9KiRQtKSkpYvHgxs2bN4rXXXsPf37/C4wICAnjjjTdqsaQ106RJE55//nnLfYOh4oZBT3nOAP7+979jMpks90+ePMmsWbO49tprKzymrj5nhYWFNGvWjMGDB/PPf/6z3ONff/01q1atYurUqcTExPDZZ58xe/ZsXnvtNXx9fW2e0973q6tUVreioiKOHz/OmDFjaNasGZcuXWLhwoX84x//4JVXXqn0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", + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2023-03-31T01:27:07.747287\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.7.1, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], "text/plain": [ - "
" + "
" ] }, "metadata": {}, @@ -466,13 +2088,1837 @@ "source": [ "t, yout = ct.step_response(Gs)\n", "\n", - "fig, ax = plt.subplots(figsize=(6, 3.5))\n", - "ax.set_title(\"Aeropêndulo em Malha Aberta\")\n", - "ax.set_ylabel(\"Ângulo (Graus°)\")\n", - "ax.set_xlabel(\"Tempo (s)\")\n", - "ax.plot(t, np.rad2deg(yout))\n", + "plt.rc('xtick', labelsize=7)\n", + "plt.rc('ytick', labelsize=7)\n", + "\n", + "fig, ax = plt.subplots(figsize=(10, 4))\n", + "ax.set_title(\"Aeropêndulo em Malha Aberta\", fontsize=10)\n", + "ax.set_ylabel(\"Ângulo (Graus°)\", fontsize=8)\n", + "ax.set_xlabel(\"Tempo (s)\", fontsize=8)\n", + "ax.plot([0, 0, t[-1]], [0, 1, 1], \"--\", lw=1.4,\n", + " label=\"Sinal Degrau Unitário U(S)\")\n", + "ax.plot(t, yout, lw=1.4, label=\"Sinal de Saída Y(S)\")\n", + "ax.legend(fontsize=7)\n", "plt.show()" ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Controlador projetado usando LGR com auxílio do Matlab\n", + "\n", + "Para fins de teste foi projetado um controlador simples usando o matlab e encontrada a função de transferência com o auxílio da biblioteca Control, por fim foi obteda a equação de diferenças para implementar o controlador no simulador.\n", + "\n", + "
\n", + "
\n", + " \n", + "

Figura 3 - Diagrama de blocos do Sistema em Malha Fechada.

\n", + "
\n", + "
\n", + "\n", + "
\n", + "\n", + "\n", + "### Função de Transferência do Controlador\n", + "\n", + "$$\n", + "\\begin{align}\n", + " C(s) &= \\frac{0,2126s + 0,7893}{s} \\tag{15}\n", + "\\end{align}\n", + "$$" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Função de Transferência do Controlador usando a biblioteca Control do Python**" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$$\\frac{0.2126 s + 0.7893}{s}$$" + ], + "text/plain": [ + "TransferFunction(array([0.2126, 0.7893]), array([1, 0]))" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numc = np.array([0.2126, 0.7893])\n", + "denc = np.array([1, 0])\n", + "\n", + "Cs = ct.tf(numc, denc)\n", + "Cs" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simulação do Sistema em Malha Fechada " + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$$\\frac{0.5937 s + 2.204}{s^3 + 0.717 s^2 + 10.58 s + 2.204}$$" + ], + "text/plain": [ + "TransferFunction(array([0.59367547, 2.20408302]), array([ 1. , 0.71698113, 10.57858113, 2.20408302]))" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Fs = ct.series(Gs, Cs)\n", + "Hs = ct.feedback(Fs, 1, sign=-1)\n", + "Hs" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'RiseTime': 10.086501381633674,\n", + " 'SettlingTime': 18.388467903439853,\n", + " 'SettlingMin': 0.9008661761428961,\n", + " 'SettlingMax': 0.9999999999999999,\n", + " 'Overshoot': 0,\n", + " 'Undershoot': 0,\n", + " 'Peak': 0.9990565919194464,\n", + " 'PeakTime': 32.819923726392645,\n", + " 'SteadyStateValue': 0.9999999999999999}" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ct.step_info(Hs)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Resposta ao degrau unitário" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2023-03-31T01:26:04.945423\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.7.1, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "t, yout = ct.step_response(Hs)\n", + "\n", + "plt.rc('xtick', labelsize=7)\n", + "plt.rc('ytick', labelsize=7)\n", + "\n", + "fig, ax = plt.subplots(figsize=(10, 4))\n", + "ax.set_title(\"Aeropêndulo em Malha Fechada\", fontsize=10)\n", + "ax.set_ylabel(\"Ângulo (Graus°)\", fontsize=8)\n", + "ax.set_xlabel(\"Tempo (s)\", fontsize=8)\n", + "ax.plot([0, 0, t[-1]], [0, 1, 1], \"--\", lw=1,\n", + " label=\"Sinal Degrau Unitário U(S)\")\n", + "ax.plot(t, yout, lw=1., label=\"Sinal de Saída Y(S)\")\n", + "ax.legend(fontsize=7)\n", + "plt.show()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Ao analisar o sistema com o controlador, temos que o sistema não possui erro em regime permanente e seu overshoot é zero, no entanto, para que esses requisitos fossem obtidos ouve um aumento no tempo de acomodação.\n", + "\n", + "

" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Função de Transferência Discreta C(z)\n", + "\n", + "Para discretizar o sistema foi usado um período de amostragem de 0,02s.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$$\\frac{0.2165 z - 0.2087}{z - 1}\\quad dt = 0.01$$" + ], + "text/plain": [ + "TransferFunction(array([ 0.2165465, -0.2086535]), array([ 1., -1.]), 0.01)" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from control.matlab import c2d\n", + "\n", + "Cz = c2d(Cs, Ts=0.01, method=\"tustin\")\n", + "Cz" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "\\begin{align}\n", + " C(z) &= \\dfrac{0,2165z −0,2087}{z-1} \\tag{17}\\\\\n", + " &= \\dfrac{0,2165z −0,2087}{z-1} \\cdot \\dfrac{z^{-1}}{z^{-1}} \\tag{18}\\\\\n", + " &= \\dfrac{0,2165 − 0,2087z^{-1}}{1-z^{-1}} \\tag{19}\\\\\n", + "\\end{align}\n", + "$$" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Encontrando a equação de diferenças do controlador\n", + "\n", + "$$\n", + "\\begin{align}\n", + " C(z) &= \\dfrac{U(z)}{E(z)} \\tag{20}\n", + "\\end{align}\n", + "$$\n", + "\n", + "onde:\n", + "\n", + "$$\n", + "\\begin{align}\n", + " U(z) &= Z\\{u[k]\\} \\tag{21}\\\\\n", + " E(z) &= Z\\{e[k]\\} \\tag{22}\n", + "\\end{align}\n", + "$$\n", + "\n", + "\n", + "$$\n", + "\\begin{align}\n", + " \\dfrac{U(z)}{E(z)} &= \\dfrac{0,2165 − 0,2087z^{-1}}{1-z^{-1}} \\tag{23}\\\\\n", + " (1-z^{-1})U(z) &= (0,2165 − 0,2087z^{-1})E(z) \\tag{24}\\\\\n", + " U(z)-z^{-1}U(z) &= 0,2165E(z) − 0,2087z^{-1}E(z) \\tag{25}\\\\\n", + " Z^{-1}\\{U(z)-z^{-1}U(z)\\} &= Z^{-1}\\{0,2165E(z) − 0,2087z^{-1}E(z)\\} \\tag{26}\\\\\n", + " u[k] − u[k − 1] &= 0,2165e[k] − 0,2087e[k − 1] \\tag{27}\\\\\n", + " u[k] &= u[k − 1] + 0,2165e[k] − 0,2087e[k − 1] \\tag{28}\n", + "\\end{align}\n", + "$$\n", + "\n", + "
\n", + "\n", + "Agora é possível implementar uma classe python para o controlador a partir da equação de diferenças\n", + "\n", + "
\n", + "\n", + "$$\n", + "\\begin{align}\n", + " u[k] &= u[k − 1] + 0,2165e[k] − 0,2087e[k − 1] \\tag{29}\n", + "\\end{align}\n", + "$$" + ] } ], "metadata": { diff --git a/simulacao_modelagem_aeropendulo/README.md b/simulacao_modelagem_aeropendulo/README.md index ebd1ddd..c2257c2 100644 --- a/simulacao_modelagem_aeropendulo/README.md +++ b/simulacao_modelagem_aeropendulo/README.md @@ -1,20 +1,75 @@ - +--- +title: Simulação Gráfica do Aeropêndulo com a Biblioteca **VPython** +author: Oséias Farias + +--- -# Simulação Gráfica do Aeropêndulo com a Biblioteca **VPython** + -Sistemas de controle têm como objetivos modelar, controlar e regular o comportamento de um processo ou sistema físico. Ele é amplamente utilizado em diversas áreas, como engenharia, física, química e biologia, para garantir que o sistema ou processo seja mantido dentro de um determinado conjunto de parâmetros ou condições.
- +
+
+ +
+Universidade Federal do Pará +
+
+Campus Universitário de Tucuruí +
+
+Faculdade de Engenharia Elétrica +
+ +
+ +Projeto: Laboratório Virtual de Sistema de Controle\ +Título:: Simulação Gráfica do Aeropêndulo com a Biblioteca VPython\ +Autor: +Oséias Farias\ +Orientadores:\ +Prof. Dr: Raphael Teixeira\ +Prof. Dr: Rafael Bayma + +
+ + + +## Demostração Simulador + +
+ +
+ +## Objetivo de Sistemas de Controle + +

Sistemas de controle têm como objetivos modelar, controlar e regular o comportamento de um processo ou sistema físico. Ele é amplamente utilizado em diversas áreas, como engenharia, física, química e biologia, para garantir que o sistema ou processo seja mantido dentro de um determinado conjunto de parâmetros ou condições.

+ +
+
+ -

Figura 1 - Animação do aeropêndulo usando a biblioteca vpython.

+

Figura 1 - Diagrama de blocos do Sistema em Malha Fechada.

-Nas Engenharias, muito dos sistemas estudados são físicos, quando se modela matematicamente esses sistemas, fica complicado para o aluna assimilar o comportamento do sistema real a partir dos gráficos dos estados, por outro lado, a implementação de protótipos se torna um empecilho para o processo de aprendizagem, já que demanda conhecimento de outra áreas, além do custo na compra de componentes, sendo assim, a simulação gráfica desses sistemas usando liguagens de programação proporciona ao aluno uma excelente forma de visualizar o comportamento do sistema real sem custos de implementação já que as linguagens de programação são gratuitas. +

Nas Engenharias, muito dos sistemas estudados são físicos, quando se modela matematicamente esses sistemas, fica complicado para o aluna assimilar o comportamento do sistema real a partir dos gráficos dos estados, por outro lado, a implementação de protótipos se torna um empecilho para o processo de aprendizagem, já que demanda conhecimento de outra áreas, além do custo na compra de componentes, sendo assim, a simulação gráfica desses sistemas usando liguagens de programação proporciona ao aluno uma excelente forma de visualizar o comportamento do sistema real sem custos de implementação já que as linguagens de programação são gratuitas.

-Para a implementação da simulação gráfica do Aeropêndulo, foi usada a linguagem de programação Python com a biblioteca Vpython, a Figura 2 mostra o simulador. +

Para a implementação da simulação gráfica do Aeropêndulo, foi usada a linguagem de programação Python com a biblioteca Vpython, a Figura 2 mostra o simulador.

@@ -24,11 +79,22 @@ Para a implementação da simulação gráfica do Aeropêndulo, foi usada a ling
+ ## O que é o Aeropêndulo? -O aeropêndulo é um dispositivo utilizado em experimentos de física que combina os princípios de um pêndulo e da aerodinâmica. Ele consiste em uma haste suspensa por um ponto fixo em um suporte, com uma asa em uma das extremidades da haste. +

O aeropêndulo é um dispositivo utilizado em experimentos de física que combina os princípios de um pêndulo e da aerodinâmica. Ele consiste em uma haste suspensa por um ponto fixo em um suporte, com uma asa em uma das extremidades da haste.

+ + +
+
+ +

Figura 3 - Aeropêndulo.

+
+
+ -Quando o aeropêndulo é movido para um lado, a força da gravidade faz com que a haste comece a oscilar em torno do ponto de suspensão. A asa no final da haste também gera uma força aerodinâmica que pode afetar o movimento do pêndulo. A interação entre as forças gravitacionais e aerodinâmicas faz com que o aeropêndulo execute movimentos complexos e interessantes. +

Quando o aeropêndulo é movido para um lado, a força da gravidade faz com que a haste comece a oscilar em torno do ponto de suspensão. A asa no final da haste também gera uma força aerodinâmica que pode afetar o movimento do pêndulo. A interação entre as forças gravitacionais e aerodinâmicas faz com que o aeropêndulo execute movimentos complexos e interessantes.


@@ -40,80 +106,97 @@ Quando o aeropêndulo é movido para um lado, a força da gravidade faz com que
- -

Figura 3 - Diagrama esquemático do Aeropêndulo.

+ +

Figura 4 - Diagrama esquemático do Aeropêndulo.

-Usando as leis de Newton e momentos angulares podemos encontrar o modelo matemático que descreve a dinâmica do aeropêndulo, assim, temos a equação $$(1)$$ que modela o sistema em questão. +

Usando as leis de Newton e momentos angulares podemos encontrar o modelo matemático que descreve a dinâmica do aeropêndulo, assim, temos a equação $\bf(01)$ que modela o sistema em questão.

-$$\begin{align} - T &= J\ddot{\theta} + c\dot{\theta} +mgd\sin{\theta} \tag{1}\\ +$$ +\begin{align} + T &= J\ddot{\theta} + c\dot{\theta} +mgd\sin{(\theta)} \tag{01} \end{align} $$ -Onde: - -
    -
  • T: Empuxo gerado pela hélice;
  • -
  • J: Momento de inércia;
  • -
  • θ: posição angular do Aeropêndulo;
  • -
  • c: coeficiente de amortecimento viscoso;
  • -
  • m: peso do Aeropêndulo;
  • -
  • d: a distância entre o centro de massa e o ponto de pivô;
  • -
- -## Linearização do Sistema - -Uma das técnicas de linearização quando se tem sistemas não lineares que a componente não linear é o seno ou cosseno é considerar o seno ou cosseno sendo o valor do próprio ângulo, isso funciona bem para pequenas variações em torno do ângulo, aplicando essa técnica ao modelo do aeropêndulo, temos a equação $$(2)$$. +

Queremos controlar o ângulo do braço do aeropêndulo a partir da tensão aplicada aos terminais do motor, assim,devemos encontrar uma relação entre a tensão $\bf V$ nos terminais do motor e o empuxo $\bf T$ gerado pela hélice, essa relação é não linear, porém é possível aproximar por uma relação linear, como mostra a expressão $\bf(02)$.

$$ \begin{align} - T &= J\ddot{\theta} + c\dot{\theta} +mgd\theta \tag{2}\\ +    T &\approx K_mV \tag{02} \\ +    K_mV &= J\ddot{\theta} + c\dot{\theta} +mgd\sin{(\theta)} \tag{03} \end{align} $$ -Aplicando a transformada de Laplace, temos: +
-$$ -\begin{align} - T(S) &= S^2J\theta(S) + Sc\theta(S) +mgd\theta(S) \tag{3}\\ - T(S) &= (S^2J + Sc +mgd)\theta(S) \tag{4}\\ - \frac{\theta(S)}{T(S)} &= \frac{1}{S^2J + Sc +mgd} \tag{5}\\ - \frac{\theta(S)}{T(S)} &= \frac{1/J}{S^2 + Sc/J +mgd/J} \tag{6}\\ -\end{align} -$$ +
+
+ +

Figura 5 - Diagrama de blocos do modelo do Aeropêndulo.

+
+
-Queremos controlar o ângulo do braço do aeropêndulo a partir da tensão aplicada aos terminais do motor, assim,devemos encontrar uma relação entre a tensão $$V$$ nos terminais do motor e o empuxo $$T$$ gerado pela hélice, essa relação é não linear, porém é possível aproximar por uma relação linear, como mostra a expressão $$(7)$$. +
$$ \begin{align} - T &\approx K_mV \tag{7}\\ +    \dot{x_2} &= x_1 \tag{04} \\ +    \dot{x_1}J &= - x_1c - mgdsen(x_2) + VK_m \tag{05} \\ +    \dot{x_1} &= \dfrac{- x_1c - mgdsen(x_2) + VK_m}{J} \tag{06} \end{align} $$ -Aplicando a transformada de Laplace, temos: + +Onde: + +
+
    +
  • T: Empuxo gerado pela hélice;
  • +
  • J: Momento de inércia;
  • +
  • θ: posição angular do Aeropêndulo;
  • +
  • c: coeficiente de amortecimento viscoso;
  • +
  • m: peso do Aeropêndulo;
  • +
  • d: a distância entre o centro de massa e o ponto de pivô;
  • +
  • V: Tensão de Entrada do Motor CC Série;
  • +
  • Km: Relação entre o torque e a tensão;
  • +
  • x1 e x2: Estados do Sistema;
  • +
+
+ +

+ +## Linearização do Sistema + +

Uma das técnicas de linearização quando se tem sistemas não lineares que a componente não linear é o seno ou cosseno é considerar o seno ou cosseno sendo o valor do próprio ângulo, isso funciona bem para pequenas variações em torno do ângulo, aplicando essa técnica ao modelo do aeropêndulo, temos a equação $\bf(07)$. +

$$ \begin{align} - T(S) &\approx K_mV(S) \tag{8}\\ + K_mV &= J\ddot{\theta} + c\dot{\theta} +mgd\theta \tag{07}\\ \end{align} $$ -Agora podemos substituir $$(8)$$ em $$(6)$$, +

Aplicando a transformada de Laplace, temos:

$$ \begin{align} - \frac{\theta(S)}{K_mV(S)} = \frac{1/J}{S^2 + Sc/J +mgd/J} \tag{9}\\ - \frac{\theta(S)}{V(S)} = \frac{K_m/J}{s^2 + Sc/J +mgd/J} \tag{10} + K_mV(s) &= s^2J\theta(s) + sc\theta(s) +mgd\theta(s) \tag{08}\\ + K_mV(s) &= (s^2J + sc +mgd)\theta(s) \tag{09}\\ + \frac{\theta(s)}{K_mV(s)} &= \frac{1}{s^2J + sc +mgd} \tag{10}\\ + \frac{\theta(s)}{K_mV(s)} &= \frac{1/J}{s^2 + sc/J +mgd/J} \tag{11}\\ + \frac{\theta(s)}{V(s)} &= \frac{K_m/J}{s^2 + sc/J +mgd/J} \tag{12} \end{align} $$ +
## Sistema no Espaço de Estados + ### Forma Canônica de Controlador $$ @@ -151,33 +234,36 @@ Y= \begin{bmatrix} \end{bmatrix} + 0 $$ + ### Parâmetros para Simulação -Para simulação foi usado os parâmetros do artigo$[1]$. + +Para simulação foi usado os parâmetros do artigo $\bf[1]$. $$ \begin{align} -\begin{array}{|c|c|} \hline -\text { Parâmetros do Aeropêndulo } & \text{Valores} \\ \hline -K_m & 0,0296 \\ \hline -d & 0,03m \\ \hline -J & 0,0106 Kgm^2 \\ \hline -m & 0,36 m \\ \hline -g & 9,8 m/s^2 \\ \hline -c & 0,0076 Nms/rad \\ \hline -\end{array} + \begin{array}{|c|c|} \hline + \text { Parâmetros do Aeropêndulo } & \text{Valores} \\ \hline + K_m & 0,0296 \\ \hline + d & 0,03m \\ \hline + J & 0,0106 Kgm^2 \\ \hline + m & 0,36 m \\ \hline + g & 9,8 m/s^2 \\ \hline + c & 0,0076 Nms/rad \\ \hline + \end{array} \end{align} $$ ---- +
## Resposta ao degrau usando Python -Para realizar a simulação da resposta ao degrau foi usado Python com o auxílio das bibliotecas numpy, matplotlib e control, sendo que as bibliotecas numpy e matplotlib são usada para criar as matrizes A, B, C e D e plotar a resposta do do sistema, respectivamente, já a biblioteca control é usada para criar o sistema no espaço de estados e obter a função de transferência, além disso, é possível obter a resposta ao degrau usando a função **step** da biblioteca control, que recebe como parâmetro o sistema criado anteriormente, no espaço de estados ou função de transferência. +

Para realizar a simulação da resposta ao degrau foi usado Python com o auxílio das bibliotecas numpy, matplotlib e control, sendo que as bibliotecas numpy e matplotlib são usada para criar as matrizes A, B, C e D e plotar a resposta do do sistema, respectivamente, já a biblioteca control é usada para criar o sistema no espaço de estados e obter a função de transferência, além disso, é possível obter a resposta ao degrau usando a função **step** da biblioteca control, que recebe como parâmetro o sistema criado anteriormente, no espaço de estados ou função de transferência.

### Importando as bibliotecas Python usadas -``` + +```python import numpy as np import matplotlib.pyplot as plt import control as ct @@ -187,7 +273,7 @@ plt.style.use("ggplot") Variáveis com os parâmetros para simulação do modelo. -``` +```python K_m = 0.0296 m = 0.36 d = 0.03 @@ -198,7 +284,7 @@ c = 0.0076 Matrizes NumPy do sistema no espaço de estados -``` +```python A = np.array([[0, 1], [-(m*g*d)/J, -(c/J)]]) @@ -215,30 +301,29 @@ D = 0
-Para criar o sistema no espaço de estados, foi usado a biblioteca Python, **control**, essa biblioteca permite criar um sistema no espaço de estados a partir das matrizes **A**, **B**, **C**, **D** +

Para criar o sistema no espaço de estados, foi usado a biblioteca Python, **control**, essa biblioteca permite criar um sistema no espaço de estados a partir das matrizes **A**, **B**, **C**, **D**

-``` +```python sys = ct.ss(A, B, C, D) print(sys) ``` ### Obtendo a Função de Transferência a partir do Espaço de Estados -Para obter a função de transferência a partir do sistema no espaço de estados, a biblioteca control implementa uma função, ct.ss2tf(sys), que recebe como parâmetro, o sistema no espaço de estados e retorna a função de transferência. +

Para obter a função de transferência a partir do sistema no espaço de estados, a biblioteca control implementa uma função, ct.ss2tf(sys), que recebe como parâmetro, o sistema no espaço de estados e retorna a função de transferência.

-``` +```python Gs = ct.ss2tf(sys) Gs ``` ### Informações do sistema em malha aberta -Antes de realizar a simulação em malha aberta, é interessante observar as características do sistema, para isso, a biblioteca control implementa algumas função. +

Antes de realizar a simulação em malha aberta, é interessante observar as características do sistema, para isso, a biblioteca control implementa algumas função.

#### Explicando as diferentes funções da biblioteca control -A função **ct.step_info()** recebe como parâmetro o sistema no espaço de estados ou uma função de transferência e retorna as características do sistema, para esse exemplo, ao aplicar a função ela retorna diversas características, exemplo: - +

A função **ct.step_info()** recebe como parâmetro o sistema no espaço de estados ou uma função de transferência e retorna as características do sistema, para esse exemplo, ao aplicar a função ela retorna diversas características, exemplo:

  • Tempo de acomodação -> 'SettlingTime': 10.308519357198815'
  • @@ -246,7 +331,7 @@ A função **ct.step_info()** recebe como parâmetro o sistema no espaço de est
  • Tempo de Subida -> 'RiseTime': 0.396481513738416
-``` +```python ct.step_info(sys) ``` @@ -264,9 +349,9 @@ ct.step_info(sys) 'SteadyStateValue': 0.2796674225245654} ``` -A função **ct.damp()** recebe como argumento o sistema no espaço de estados ou a função de transferência e retorna os Autovalores, amortecimento e frequência natural para cada polo do sistema. +

A função **ct.damp()** recebe como argumento o sistema no espaço de estados ou a função de transferência e retorna os Autovalores, amortecimento e frequência natural para cada polo do sistema.

-``` +```python ct.damp(sys); ``` @@ -278,9 +363,9 @@ _____Eigenvalue______ Damping___ Frequency_ -0.3585 -3.139j 0.1135 3.16 ``` -A função **ct.poles()** recebe como argumento o sistema no espaço de estados ou a função de transferência e retorna os polos do sistema, para esse caso o sistema é de segunda ordem, pois possui dois pólos. +

A função **ct.poles()** recebe como argumento o sistema no espaço de estados ou a função de transferência e retorna os polos do sistema, para esse caso o sistema é de segunda ordem, pois possui dois pólos.

-``` +```python ct.poles(sys) ``` @@ -290,9 +375,9 @@ ct.poles(sys) array([-0.35849057+3.13948884j, -0.35849057-3.13948884j]) ``` -A função **ct.zeros()** recebe como argumento o sistema no espaço de estados ou a função de transferência e retorna os zeros do sistema. para esse caso o sistema não possui zeros. +

A função **ct.zeros()** recebe como argumento o sistema no espaço de estados ou a função de transferência e retorna os zeros do sistema. para esse caso o sistema não possui zeros.

-``` +```python ct.zeros(sys) ``` @@ -304,7 +389,7 @@ array([], dtype=float64) #### Resposta ao degrau -``` +```python t, yout = ct.step_response(Gs) fig, ax = plt.subplots(figsize=(6, 3.5)) @@ -319,21 +404,181 @@ plt.show()
-
-
---- +

+ + +## Controlador projetado usando LGR com auxílio do Matlab + + +

Para fins de teste foi projetado um controlador simples usando o matlab e encontrada a função de transferência com o auxílio da biblioteca Control, por fim foi obtida a equação de diferenças para implementar o controlador no simulador.

+ + +
+
+ +

Figura 6 - Diagrama de blocos do Sistema em Malha Fechada.

+
+
+ + +### Função de Transferência do Controlador + + +$$ +\begin{align} +C(s) &= \frac{0,2126s + 0,7893}{s} \tag{13} +\end{align} +$$ + +**Função de Transferência do Controlador usando a biblioteca Control do Python** + +```python +numc = np.array([0.2126, 0.7893]) +denc = np.array([1, 0]) + +Cs = ct.tf(numc, denc) +print(Cs) +``` + +**saída:** + +$$ +\dfrac{0.2126 s + 0.7893}{s} +$$ + +### Simulação do Sistema em Malha Fechada + +```python +Fs = ct.series(Gs, Cs) +Hs = ct.feedback(Fs, 1, sign=-1) +Hs +``` + +**saída:** + +$$ +\dfrac{0.5937s+2.204}{s^3 +0.717s^2+10.58s+2.204} +$$ + + +### Resposta ao degrau unitário + +```python +t, yout = ct.step_response(Hs) + +plt.rc('xtick', labelsize=7) +plt.rc('ytick', labelsize=7) + +fig, ax = plt.subplots(figsize=(7, 4)) +ax.set_title("Aeropêndulo em Malha Fechada", fontsize=10) +ax.set_ylabel("Ângulo (Graus°)", fontsize=8) +ax.set_xlabel("Tempo (s)", fontsize=8) +ax.plot([0, 0, t[-1]], [0, 1, 1], "--", lw=1, + label="Sinal Degrau Unitário U(S)") +ax.plot(t, yout, lw=1., label="Sinal de Saída Y(S)") +ax.legend(fontsize=7) +plt.show() +``` + +**saída:** + +
+
+ +
+
+ + +

Ao analisar o sistema com o controlador, temos que o sistema não possui erro em regime permanente e seu overshoot é zero, no entanto, para que esses requisitos fossem obtidos ouve um aumento no tempo de acomodação.


+## Função de Transferência Discreta C(z) + +

Para discretizar o sistema foi usado um período de amostragem de 0,01s.

+ +```python +from control.matlab import c2d + +Cz = c2d(Cs, Ts=0.01, method="tustin") +Cz +``` + +$$ +\dfrac{0.2165 z + 0.2087}{z-1} \quad dt = 0.01 +$$ + +$$ +\begin{align} + C(z) &= \dfrac{0,2165z −0,2087}{z-1} \tag{14}\\ + &= \dfrac{0,2165z −0,2087}{z-1} \cdot \dfrac{z^{-1}}{z^{-1}} \tag{15}\\ + &= \dfrac{0,2165 − 0,2087z^{-1}}{1-z^{-1}} \tag{16}\\ +\end{align} +$$ + +#### Encontrando a equação de diferenças do controlador + +$$ +\begin{align} +C(z) &= \dfrac{U(z)}{E(z)} \tag{20} +\end{align} +$$ + +onde: + +$$ +\begin{align} + U(z) &= Z\{u[k]\} \tag{17}\\ + E(z) &= Z\{e[k]\} \tag{18}\\ + \dfrac{U(z)}{E(z)} &= \dfrac{0,2165 − 0,2087z^{-1}}{1-z^{-1}} \tag{19}\\ + (1-z^{-1})U(z) &= (0,2165 − 0,2087z^{-1})E(z) \tag{20}\\ + U(z)-z^{-1}U(z) &= 0,2165E(z) − 0,2087z^{-1}E(z) \tag{21}\\ + Z^{-1}\{U(z)-z^{-1}U(z)\} &= Z^{-1}\{0,2165E(z) − 0,2087z^{-1}E(z)\} \tag{22}\\ + u[k] − u[k − 1] &= 0,2165e[k] − 0,2087e[k − 1] \tag{23}\\ + u[k] &= u[k − 1] + 0,2165e[k] − 0,2087e[k − 1] \tag{24} +\end{align} +$$ + + + +

Agora é possível implementar uma classe python para o controlador a partir da equação de diferenças.

+ +$$ +\begin{align} + u[k] &= u[k − 1] + 0,2165e[k] − 0,2087e[k − 1] \tag{25} +\end{align} +$$ + +

com a função de diferenças encontrada, agora é possível implementa-la usando python e fecha a malha com o controlador para simular, essa lógica está implementada no simulador.

+ +

+ # Referências +

-
-
[1.] JOB, Mila Mary; JOSE, P. Subha Hency. Modeling and control of mechatronic aeropendulum. In: 2015 International Conference on Innovations in Information, Embedded and Communication Systems (ICIIECS). IEEE, 2015. p. 1-5.
-
...
+
[1.] JOB, Mila Mary; JOSE, P. Subha Hency. Modeling and control of mechatronic aeropendulum. In: 2015 International Conference on Innovations in Information, Embedded and Communication Systems (ICIIECS). IEEE, 2015. p. 1-5.
+ +
+ +
[2.] Silva. Yago. Projeto, construção e controle de um aeropêndulo +. Centro de Engenharia Elétrica e Informática, Departamento de Engenharia Elétrica e Informática, Universidade Federal de Campina Grande - UFCG, 2018.
+ +
+ +
[3.] MOHAMMADBAGHERI, Amin; YAGHOOBI, Mahdi. A new approach to control a driven pendulum with PID method. In: 2011 UkSim 13th International Conference on Computer Modelling and Simulation. IEEE, 2011. p. 207-211.
+ +
+ +
[4.] SILVA, Yago Luiz Monteiro et al. Projeto, construção e controle de um aeropêndulo. 2018.
+
+

\ No newline at end of file diff --git a/simulacao_modelagem_aeropendulo/aeropendulo/__init__.py b/simulacao_modelagem_aeropendulo/aeropendulo/__init__.py new file mode 100644 index 0000000..b20d0aa --- /dev/null +++ b/simulacao_modelagem_aeropendulo/aeropendulo/__init__.py @@ -0,0 +1,23 @@ +# ----------------------------------------------------- +# Universidade Federal do Pará +# Campus Universitário de Tucuruí +# Faculdade de Engenharia Elétrica +# ----------------------------------------------------- +# +# Laboratório Virtual Sistemas Dinâmicos e Controle +# Tema: Simulação Aeropêndulo +# Autor: Oséias Farias +# Orientadores: Prof. Dr: Raphael Teixeira, +# Prof. Dr: Rafael Bayma +# +# Data: 2023 +# ---------------------------------------------------- +# +from .graficos_aeropendulo import Graficos # noqa: F401 +from .animacao_aeropendulo import AnimacaoAeropendulo # noqa: F401 +from .interface_interativa import Interface # noqa: F401 +from .modelo_mat_aeropendulo import ModeloMatAeropendulo # noqa: F401 +from .implementacao_controlador import ControladorDiscreto # noqa: F401 + + +__version__ = "0.1.0" diff --git a/simulacao_modelagem_aeropendulo/aeropendulo/animacao_aeropendulo.py b/simulacao_modelagem_aeropendulo/aeropendulo/animacao_aeropendulo.py new file mode 100644 index 0000000..fad64a3 --- /dev/null +++ b/simulacao_modelagem_aeropendulo/aeropendulo/animacao_aeropendulo.py @@ -0,0 +1,220 @@ +# ----------------------------------------------------- +# Universidade Federal do Pará +# Campus Universitário de Tucuruí +# Faculdade de Engenharia Elétrica +# ----------------------------------------------------- +# +# Laboratório Virtual Sistemas Dinâmicos e Controle +# Tema: Simulação Aeropêndulo +# Autor: Oséias Farias +# Orientadores: Prof. Dr: Raphael Teixeira, +# Prof. Dr: Rafael Bayma +# +# Data: 2023 +# ---------------------------------------------------- +# +import vpython as vp + + +class AnimacaoAeropendulo: + """ + Classe que implementa a aminação do Aeropêndulo. + + Atributo: + comprimento_braco: tamanho do braço do Aeropêndulo. + """ + def __init__(self, comprimento_braco=4.4) -> None: + # Parâmetros do Aeropêndulo + self.comprimento_braco = comprimento_braco + self.scene = vp.canvas(title="

Aeropêndulo

", + width=650, + height=580, align="left", autoscale=0, range=5, + center=vp.vec(0, 3, 0), + background=vp.vector(1.7, 0.7, 0.9), + color=vp.vec(1, 0.6, 0.6), + forward=vp.vec(-0.3, 0, -1)) + self.scene.range = 6 + # chamando a função para criar a aminação gráfica do Aeropêndulo. + self.aeropendulo = self.__aminacao() + self.__helice() + + def __aminacao(self) -> vp.compound: + """ + Classe que implementa o Aeropêndulo. + + Args: + comprimento_braco: tamanho do braço do Aeropêndulo. + Returns: + Retorna um objeto (vpython) que contêm a estrutura do Aeropêndulo. + """ + self.base = vp.box(pos=vp.vec(0, -0.85, 0), size=vp.vec(30, 0.2, 15), + texture=vp.textures.wood) + self.parede = vp.box(pos=vp.vec(0, 7.1, -7.55), + size=vp.vec(30, 16, 0.2), + color=vp.vec(0.1, 0.1, 0.1), shininess=0.01) + self.sitio = vp.text(pos=vp.vec(0, 8.1, -7.45), + text="AEROPÊNDULO", color=vp.vec(1, 0.6, 0.6), + align='center', depth=0) + + self.__desenhar_pendulo() + + # Eixo de sustentação. + self.eixo = vp.cylinder(pos=vp.vec(0, 5.2, 0.3), radius=0.09, + axis=vp.vec(0, 0, -2), + color=vp.vec(0.7, 0.4, 0.1)) + + # Estrutura de sustentação do aeropêndulo. + self.b1 = vp.box(pos=vp.vec(0, 1.7, -2), size=vp.vec(3, 8, 0.6), + color=vp.vec(0.8, 0.8, 0.8)) + + self.b2 = vp.box(pos=vp.vec(0, -0.6, -1.5), size=vp.vec(4.5, 0.4, 2.5), + color=vp.vec(0.8, 0.8, 0.8)) + + self.logo = vp.box(pos=vp.vec(0, 2.5, -1.799), + texture="https://i.imgur.com/D2xnkpF.png", + size=vp.vec(2, 2, 0.2)) + + self.ufpa = vp.text(pos=vp.vec(0, 3.7, -1.7), text="UFPA", + color=vp.vec(1, 0.6, 0.6), height=0.5, + align='center', depth=0) + + return self.pendulo + + def __helice(self) -> None: + self.helice = vp.box(pos=vp.vec(0.8, 0.6, 0), + size=vp.vec(0.05, 0.2, 2), + color=vp.vec(1, 1, 0)) + + self.helice1 = vp.box(pos=vp.vec(0.8, 0.6, 0), + size=vp.vec(0.05, 0.2, 2), + color=vp.vec(1, 1, 0)) + self.helice1.axis = self.pendulo.axis + self.helice1.size = vp.vec(0.05, 0.2, 2) + self.helice1.rotate(axis=vp.vec(1, 0, 0), + angle=vp.pi/4) + + self.helice2 = vp.box(pos=vp.vec(0.8, 0.6, 0), + size=vp.vec(0.05, 0.2, 2), + color=vp.vec(1, 1, 0)) + self.helice2.axis = self.pendulo.axis + self.helice2.size = vp.vec(0.05, 0.2, 2) + self.helice2.rotate(axis=vp.vec(1, 0, 0), + angle=vp.pi/2) + + self.helice3 = vp.box(pos=vp.vec(0.8, 0.6, 0), + size=vp.vec(0.05, 0.2, 2), + color=vp.vec(1, 1, 0)) + self.helice3.axis = self.pendulo.axis + self.helice3.size = vp.vec(0.05, 0.2, 2) + self.helice3.rotate(axis=vp.vec(1, 0, 0), + angle=3*vp.pi/4.) + self.helice1.visible = False + self.helice2.visible = False + self.helice3.visible = False + + def pause_giro(self) -> None: + self.helice1.visible = True + self.helice2.visible = True + self.helice3.visible = True + + def girar_helice(self) -> None: + self.helice1.visible = False + self.helice2.visible = False + self.helice3.visible = False + + def set_posicao_helice(self, angle): + self.helice.rotate(axis=vp.vec(0, 0, 1), + angle=angle, + origin=vp.vec(0, 5.2, 0)) + self.helice.size = vp.vec(0.05, 0.2, 2) + + self.helice1.rotate(axis=vp.vec(0, 0, 1), + angle=angle, + origin=vp.vec(0, 5.2, 0)) + self.helice1.size = vp.vec(0.05, 0.2, 2) + + self.helice2.rotate(axis=vp.vec(0, 0, 1), + angle=angle, + origin=vp.vec(0, 5.2, 0)) + self.helice2.size = vp.vec(0.05, 0.2, 2) + + self.helice3.rotate(axis=vp.vec(0, 0, 1), + angle=angle, + origin=vp.vec(0, 5.2, 0)) + self.helice3.size = vp.vec(0.05, 0.2, 2) + + def update_helice(self, angle, ts) -> None: + + self.helice.size = vp.vec(0.05, 0.2, 2) + self.helice1.size = vp.vec(0.05, 0.2, 2) + self.helice2.size = vp.vec(0.05, 0.2, 2) + self.helice3.size = vp.vec(0.05, 0.2, 2) + + self.helice.axis = self.pendulo.axis + self.helice.size = vp.vec(0.05, 0.2, 2) + self.helice1.axis = self.pendulo.axis + self.helice1.size = vp.vec(0.05, 0.2, 2) + self.helice2.axis = self.pendulo.axis + self.helice2.size = vp.vec(0.05, 0.2, 2) + self.helice3.axis = self.pendulo.axis + self.helice3.size = vp.vec(0.05, 0.2, 2) + + self.helice.rotate(axis=vp.vec(0, 0, 1), + angle=angle*ts, + origin=vp.vec(0, 5.2, 0)) + self.helice.size = vp.vec(0.05, 0.2, 2) + + self.helice1.rotate(axis=vp.vec(0, 0, 1), + angle=angle*ts, + origin=vp.vec(0, 5.2, 0)) + self.helice1.size = vp.vec(0.05, 0.2, 2) + + self.helice2.rotate(axis=vp.vec(0, 0, 1), + angle=angle*ts, + origin=vp.vec(0, 5.2, 0)) + self.helice2.size = vp.vec(0.05, 0.2, 2) + + self.helice3.rotate(axis=vp.vec(0, 0, 1), + angle=angle*ts, + origin=vp.vec(0, 5.2, 0)) + self.helice3.size = vp.vec(0.05, 0.2, 2) + + # obs tentando ajustar o diro das hélices apenas para um lado .... + # if x[1] + interface.valor_angle < np.pi/2: + # ag = 0.3 + # else: + # ag = -0.8 + + self.helice.rotate(axis=vp.vec(1, 0, 0), angle=0.09) + self.helice1.rotate(axis=vp.vec(1, 0, 0), angle=0.09) + self.helice2.rotate(axis=vp.vec(1, 0, 0), angle=0.09) + self.helice3.rotate(axis=vp.vec(1, 0, 0), angle=0.09) + + def __desenhar_pendulo(self) -> None: + # Braço do Aeropêndulo. + self.barra = vp.box(pos=vp.vec(0, -1.4, 0), + size=vp.vec(0.2, self.comprimento_braco, 0.2), + color=vp.vec(0.5, 0.5, 0.95)) + + # Base que acopla o motor ao braço. + self.base_motor = vp.cylinder(pos=vp.vec(-0.2, -4, 0), radius=0.4, + axis=vp.vec(0.4, 0, 0), + color=vp.vec(0.5, 0.5, 0.95)) + # Armadura do motor. + self.base2_motor = vp.box(pos=vp.vec(0.4, -4, 0), + size=vp.vec(0.4, 0.4, 0.4), + color=vp.vec(1, 1, 0)) + + # Eixo que da hélice do motor + self.base_helice = vp.cylinder(pos=vp.vec(0.4, -4, 0), radius=0.05, + axis=vp.vec(0.4, 0, 0), + color=vp.vec(0.5, 0.5, 0.8)) + + # Motor completo. + self.motor = vp.compound([self.base_motor, + self.base2_motor, + self.base_helice]) + + # Aeropêndulo + self.pendulo = vp.compound([self.barra, self.motor]) + self.pendulo.pos = vp.vec(0.31, 2.7, 0) diff --git a/simulacao_modelagem_aeropendulo/aeropendulo/graficos_aeropendulo.py b/simulacao_modelagem_aeropendulo/aeropendulo/graficos_aeropendulo.py new file mode 100644 index 0000000..ae18112 --- /dev/null +++ b/simulacao_modelagem_aeropendulo/aeropendulo/graficos_aeropendulo.py @@ -0,0 +1,59 @@ +# ----------------------------------------------------- +# Universidade Federal do Pará +# Campus Universitário de Tucuruí +# Faculdade de Engenharia Elétrica +# ----------------------------------------------------- +# +# Laboratório Virtual Sistemas Dinâmicos e Controle +# Tema: Simulação Aeropêndulo +# Autor: Oséias Farias +# Orientadores: Prof. Dr: Raphael Teixeira, +# Prof. Dr: Rafael Bayma +# +# Data: 2023 +# ---------------------------------------------------- +# +import vpython as vp +from typing import Tuple + + +class Graficos: + """ + Gráfico para polagem dos dados dos estados do Aeroèndulo. + """ + def __init__(self, largura=650, altura=400): + self.width = largura + self.height = altura + + def graficos(self) -> Tuple: + """ + Método que cria os Gráfico. + + Returns: + Retorna uma tupla contendo o objeto do gráfico e da curvas. + """ + titulo = "Gráficos dos estados do Aeropêndulo" + self.grafico = vp.graph(title=titulo, align="right", + xtitle='tempo (s)', fast=True, + width=self.width, height=self.height, + center=vp.vector(0, 12, 0), scroll=True, + xmin=0, xmax=14, ymin=-0.5, ymax=6, dot=True, + background=vp.vector(0.95, 0.95, 0.95)) + + self.curva1 = vp.gcurve(color=vp.color.blue, width=3, + markers=False, label="Posição Angular (rad)", + dot=True, dot_color=vp.color.blue) + + self.curva2 = vp.gcurve(color=vp.color.black, width=3, markers=False, + label="Referência Angular(rad)", dot=True, + dot_color=vp.color.black) + + self.curva3 = vp.gcurve(color=vp.color.red, width=3, markers=False, + label="Velocidade Angular (rad/s)", dot=True, + dot_color=vp.color.red) + + self.curva4 = vp.gcurve(color=vp.color.orange, width=3, markers=False, + label="Sinal de Controle (V)", dot=True, + dot_color=vp.color.orange) + + return self.grafico, self.curva1, self.curva2, self.curva3, self.curva4 diff --git a/simulacao_modelagem_aeropendulo/aeropendulo/implementacao_controlador.py b/simulacao_modelagem_aeropendulo/aeropendulo/implementacao_controlador.py new file mode 100644 index 0000000..be6ae9d --- /dev/null +++ b/simulacao_modelagem_aeropendulo/aeropendulo/implementacao_controlador.py @@ -0,0 +1,48 @@ +# ----------------------------------------------------- +# Universidade Federal do Pará +# Campus Universitário de Tucuruí +# Faculdade de Engenharia Elétrica +# ----------------------------------------------------- +# +# Laboratório Virtual Sistemas Dinâmicos e Controle +# Tema: Simulação Aeropêndulo +# Autor: Oséias Farias +# Orientadores: Prof. Dr: Raphael Teixeira, +# Prof. Dr: Rafael Bayma +# +# Data: 2023 +# ---------------------------------------------------- +# + +class ControladorDiscreto: + def __init__(self, referencia=1, T=0.0625): + self.uk = 0 + self.uk1 = 0 + self.ek = 0 + self.ek1 = 0 + self.yout = 0 + self.k = 0 + self.r = referencia + self.T = T + + # Pega o sinal do sensor + def set_sensor(self, yout): + self.yout = yout + + # disponibiliza o sinal de controle + def get_u(self): + return self.uk + + # Calcula o sinal de controle Proporcional Integral + def control_pi(self): + self.ek = self.r - self.yout + self.uk = self.uk1 + 0.2165 * self.ek - 0.2087 * self.ek1 + self.ek1 = self.ek + self.uk1 = self.uk + self.k = self.k + 1 + + # Calcula o sinal de controle Proporcional + def controle_proporcional(self, kp=1.0): + self.ek = self.r - self.yout + self.KP = kp + self.uk = self.KP * self.ek diff --git a/simulacao_modelagem_aeropendulo/aeropendulo/interface_interativa.py b/simulacao_modelagem_aeropendulo/aeropendulo/interface_interativa.py new file mode 100644 index 0000000..86196e6 --- /dev/null +++ b/simulacao_modelagem_aeropendulo/aeropendulo/interface_interativa.py @@ -0,0 +1,78 @@ +# ----------------------------------------------------- +# Universidade Federal do Pará +# Campus Universitário de Tucuruí +# Faculdade de Engenharia Elétrica +# ----------------------------------------------------- +# +# Laboratório Virtual Sistemas Dinâmicos e Controle +# Tema: Simulação Aeropêndulo +# Autor: Oséias Farias +# Orientadores: Prof. Dr: Raphael Teixeira, +# Prof. Dr: Rafael Bayma +# +# Data: 2023 +# ---------------------------------------------------- +# +import vpython as vp + + +class Interface: + """ + Classe que implementa a interface interativa do simulador do Aeropêndulo. + + Atributo: + animacao_aeropendulo: Instância da classe AnimacaoAeropendulo. + controlador: Instância da classe AnimacaoAeropendulo. + """ + def __init__(self, animacao_aeropendulo, controlador) -> None: + self.EXE = False + self.valor_angle = 0.0 + self.controlador = controlador + self.animacao_aeropendulo = animacao_aeropendulo + self.scene = animacao_aeropendulo.scene + + # Criando a interface + self.__criar_interface() + + def __executar(self, b) -> None: + if self.EXE: + self.animacao_aeropendulo.girar_helice() + b.text = "Executar" + else: + b.text = "Pausar" + self.animacao_aeropendulo.pause_giro() + self.EXE = not self.EXE + + def rotate(self, angle) -> None: + self.valor_angle = (angle.number)*(vp.pi/180.0) + self.animacao_aeropendulo.aeropendulo.rotate(axis=vp.vec(0, 0, 1), + angle=self.valor_angle, + origin=vp.vec(0, 5.2, 0)) + self.animacao_aeropendulo.set_posicao_helice(self.valor_angle) + + def __slide_angle_referencia(self, valor) -> None: + self.controlador.r = valor.value + print(valor.value) + + def __criar_interface(self) -> None: + self.scene.append_to_caption( + "\tMenu Interativo Aeropêndulo\n") + self.scene.append_to_caption("\n\t ") + self.buttom_exe = vp.button(bind=self.__executar, + text="Excecutar", + color=vp.color.white, + background=vp.color.red, + width=100, _height=40) + self.scene.append_to_caption("\t\t") + self.scene.append_to_caption( + "Posição Inicial\t") + vp.winput(bind=self.rotate, prompt="Rotate: ", type="numeric", + width=100, _height=40) + vp.wtext(text=" Graus") + self.scene.append_to_caption('\n') + + self.scene.append_to_caption("\n\n\t") + self.scene.append_to_caption("Referência : ") + vp.slider(bind=self.__slide_angle_referencia, min=0, max=2, + step=0.001, value=0) + self.scene.append_to_caption("\n\n") diff --git a/simulacao_modelagem_aeropendulo/modelo_mat_aeropendulo.py b/simulacao_modelagem_aeropendulo/aeropendulo/modelo_mat_aeropendulo.py similarity index 90% rename from simulacao_modelagem_aeropendulo/modelo_mat_aeropendulo.py rename to simulacao_modelagem_aeropendulo/aeropendulo/modelo_mat_aeropendulo.py index 097bf66..f6c9b1a 100644 --- a/simulacao_modelagem_aeropendulo/modelo_mat_aeropendulo.py +++ b/simulacao_modelagem_aeropendulo/aeropendulo/modelo_mat_aeropendulo.py @@ -3,12 +3,13 @@ # Campus Universitário de Tucuruí # Faculdade de Engenharia Elétrica # ----------------------------------------------------- -# # Laboratório Virtual Sistemas Dinâmicos e Controle # Tema: Simulação Aeropêndulo # Autor: Oséias Farias # Orientadores: Prof. Dr: Raphael Teixeira, # Prof. Dr: Rafael Bayma +# +# Data: 2023 # ---------------------------------------------------- import numpy as np @@ -53,11 +54,18 @@ def __init__(self, x_0: List[float] = [0.1, -0.5], K_m: float = 0.0296, self.x = x_0 self.x1: List[List[float]] = [[], []] + # Sinal de Entrada + self.u = 0.0 + # Sinulação self.simu = False self.simu_dinamic = False - def modelo_aeropendulo(self, x: List[float], t: Array1XN) -> Array1XN: + def set_u(self, u): + self.u = u + + def modelo_aeropendulo(self, x: List[float] | Array1XN, + t: float | Array1XN) -> Array1XN: """ Método que implementa o modelo matemático do aeropêndulo. Args: @@ -66,12 +74,15 @@ def modelo_aeropendulo(self, x: List[float], t: Array1XN) -> Array1XN: Returns: Retorna um array numpy contendo a derivada dos estados. """ - x1, x2 = x # Variáveis de estado a partir do vetor de estados; - dx1 = x2 # Função de estado dx1 = f(x,u) + # Variáveis de estado a partir do vetor de estados + x1, x2 = x + + # Equação de estado dx2 = f(x, u) + dx2 = x1 - # Função de estado dx2 = f(x,u) - dx2 = -(self.m*self.g*self.d/self.J)*x1-(self.c/self.J)*x2 +\ - (self.K_m/self.J)*4. + # Equação de estado dx1 = f(x, u) + dx1 = (- x1*self.c - self.m*self.g*self.d*np.sin(x2) + + self.u*self.K_m) / (self.J) dx = np.array([dx1, dx2]) # Derivada do vetor de estados return dx # Retorna a derivada do vetor de estados diff --git a/simulacao_modelagem_aeropendulo/aeropendulo_doc.html b/simulacao_modelagem_aeropendulo/aeropendulo_doc.html new file mode 100644 index 0000000..0b469ab --- /dev/null +++ b/simulacao_modelagem_aeropendulo/aeropendulo_doc.html @@ -0,0 +1,698 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Simulação Gráfica do Aeropêndulo com a Biblioteca VPython + + + + + + + + +
+
+ +
+ + + +
+
+

+
+
+
+Universidade Federal do Pará +
+
+Campus Universitário de Tucuruí +
+
+Faculdade de Engenharia Elétrica +
+


+

Projeto: Laboratório Virtual de Sistema de Controle
+Título:: Simulação Gráfica do Aeropêndulo com a Biblioteca VPython
+Autor: Oséias Farias
+Orientadores:
+Prof. Dr: Raphael Teixeira
+Prof. Dr: Rafael Bayma

+


+ +

Demostração Simulador

+
+ +
+ +


+

Objetivo de Sistemas de Controle

+
+

+Sistemas de controle têm como objetivos modelar, controlar e regular o comportamento de um processo ou sistema físico. Ele é amplamente utilizado em diversas áreas, como engenharia, física, química e biologia, para garantir que o sistema ou processo seja mantido dentro de um determinado conjunto de parâmetros ou condições. +

+
+
+
+
+ +

+Figura 1 - Diagrama de blocos do Sistema em Malha Fechada. +

+
+
+
+

+Nas Engenharias, muito dos sistemas estudados são físicos, quando se modela matematicamente esses sistemas, fica complicado para o aluna assimilar o comportamento do sistema real a partir dos gráficos dos estados, por outro lado, a implementação de protótipos se torna um empecilho para o processo de aprendizagem, já que demanda conhecimento de outra áreas, além do custo na compra de componentes, sendo assim, a simulação gráfica desses sistemas usando liguagens de programação proporciona ao aluno uma excelente forma de visualizar o comportamento do sistema real sem custos de implementação já que as linguagens de programação são gratuitas. +

+
+
+

+Para a implementação da simulação gráfica do Aeropêndulo, foi usada a linguagem de programação Python com a biblioteca Vpython, a Figura 2 mostra o simulador. +

+
+
+
+
+ +

+Figura 2 - Animação do aeropêndulo usando a biblioteca vpython. +

+
+
+

O que é o Aeropêndulo?

+
+

+O aeropêndulo é um dispositivo utilizado em experimentos de física que combina os princípios de um pêndulo e da aerodinâmica. Ele consiste em uma haste suspensa por um ponto fixo em um suporte, com uma asa em uma das extremidades da haste. +

+
+
+
+
+ +

+Figura 3 - Aeropêndulo. +

+
+
+
+

+Quando o aeropêndulo é movido para um lado, a força da gravidade faz com que a haste comece a oscilar em torno do ponto de suspensão. A asa no final da haste também gera uma força aerodinâmica que pode afetar o movimento do pêndulo. A interação entre as forças gravitacionais e aerodinâmicas faz com que o aeropêndulo execute movimentos complexos e interessantes. +

+
+


+
+


+

Modelagem e Simulação Aeropêndulo

+
+
+ +

+Figura 4 - Diagrama esquemático do Aeropêndulo. +

+
+
+
+

+Usando as leis de Newton e momentos angulares podemos encontrar o modelo matemático que descreve a dinâmica do aeropêndulo, assim, temos a equação \(\bf(01)\) que modela o sistema em questão. +

+
+

\[ +\begin{align} + T &= J\ddot{\theta} + c\dot{\theta} +mgd\sin{(\theta)} \tag{01} +\end{align} +\]

+
+

+Queremos controlar o ângulo do braço do aeropêndulo a partir da tensão aplicada aos terminais do motor, assim,devemos encontrar uma relação entre a tensão \(\bf V\) nos terminais do motor e o empuxo \(\bf T\) gerado pela hélice, essa relação é não linear, porém é possível aproximar por uma relação linear, como mostra a expressão \(\bf(02)\). +

+
+

\[ +\begin{align} +    T &\approx K_mV \tag{02} \\ +    K_mV &= J\ddot{\theta} + c\dot{\theta} +mgd\sin{(\theta)} \tag{03} +\end{align} +\]

+


+
+
+ +

+Figura 5 - Diagrama de blocos do modelo do Aeropêndulo. +

+
+
+


+

\[ +\begin{align} +    \dot{x_2} &= x_1 \tag{04} \\ +    \dot{x_1}J &= - x_1c - mgdsen(x_2) + VK_m \tag{05} \\ +    \dot{x_1} &= \dfrac{- x_1c - mgdsen(x_2) + VK_m}{J} \tag{06} +\end{align} +\]

+

Onde:

+
+
    +
  • +T: Empuxo gerado pela hélice; +
  • +
  • +J: Momento de inércia; +
  • +
  • +θ: posição angular do Aeropêndulo; +
  • +
  • +c: coeficiente de amortecimento viscoso; +
  • +
  • +m: peso do Aeropêndulo; +
  • +
  • +d: a distância entre o centro de massa e o ponto de pivô; +
  • +
  • +V: Tensão de Entrada do Motor CC Série; +
  • +
  • +Km: Relação entre o torque e a tensão; +
  • +
  • +x1 e x2: Estados do Sistema; +
  • +
+
+



+

Linearização do Sistema

+
+

+Uma das técnicas de linearização quando se tem sistemas não lineares que a componente não linear é o seno ou cosseno é considerar o seno ou cosseno sendo o valor do próprio ângulo, isso funciona bem para pequenas variações em torno do ângulo, aplicando essa técnica ao modelo do aeropêndulo, temos a equação \(\bf(07)\). +

+
+

\[ +\begin{align} + K_mV &= J\ddot{\theta} + c\dot{\theta} +mgd\theta \tag{07}\\ +\end{align} +\]

+
+

+Aplicando a transformada de Laplace, temos: +

+
+

\[ +\begin{align} + K_mV(s) &= s^2J\theta(s) + sc\theta(s) +mgd\theta(s) \tag{08}\\ + K_mV(s) &= (s^2J + sc +mgd)\theta(s) \tag{09}\\ + \frac{\theta(s)}{K_mV(s)} &= \frac{1}{s^2J + sc +mgd} \tag{10}\\ + \frac{\theta(s)}{K_mV(s)} &= \frac{1/J}{s^2 + sc/J +mgd/J} \tag{11}\\ + \frac{\theta(s)}{V(s)} &= \frac{K_m/J}{s^2 + sc/J +mgd/J} \tag{12} +\end{align} +\]

+


+

Sistema no Espaço de Estados

+

Forma Canônica de Controlador

+

\[ +\begin{align} + x_1&=\theta \quad x_2=\dot{\theta} \quad x_2 = \dot{x_1} +\end{align} +\]

+

\[ +\begin{bmatrix} + \dot{x}_1 \\ + \dot{x}_2 +\end{bmatrix}= +\begin{bmatrix} + 0 & 1\\ + -\frac{mgd}{J} & -\frac{c}{J} +\end{bmatrix}\cdot +\begin{bmatrix} + x_1 \\ + x_2 +\end{bmatrix}+ +\begin{bmatrix} + 0 \\ + \frac{K_m}{J} +\end{bmatrix}\cdot u +\]

+

\[ +Y= \begin{bmatrix} + 1 & 0 +\end{bmatrix} \cdot +\begin{bmatrix} + 0 \\ + \frac{K_m}{J} +\end{bmatrix} + 0 +\]

+

Parâmetros para Simulação

+

Para simulação foi usado os parâmetros do artigo \(\bf[1]\).

+

\[ +\begin{align} + \begin{array}{|c|c|} \hline + \text { Parâmetros do Aeropêndulo } & \text{Valores} \\ \hline + K_m & 0,0296 \\ \hline + d & 0,03m \\ \hline + J & 0,0106 Kgm^2 \\ \hline + m & 0,36 m \\ \hline + g & 9,8 m/s^2 \\ \hline + c & 0,0076 Nms/rad \\ \hline + \end{array} +\end{align} +\]

+


+

Resposta ao degrau usando Python

+
+

+Para realizar a simulação da resposta ao degrau foi usado Python com o auxílio das bibliotecas numpy, matplotlib e control, sendo que as bibliotecas numpy e matplotlib são usada para criar as matrizes A, B, C e D e plotar a resposta do do sistema, respectivamente, já a biblioteca control é usada para criar o sistema no espaço de estados e obter a função de transferência, além disso, é possível obter a resposta ao degrau usando a função step da biblioteca control, que recebe como parâmetro o sistema criado anteriormente, no espaço de estados ou função de transferência. +

+
+

Importando as bibliotecas Python usadas

+ +

Variáveis com os parâmetros para simulação do modelo.

+ +

Matrizes NumPy do sistema no espaço de estados

+ +


+

Sistema no Espaço de Estados

+


+
+

+Para criar o sistema no espaço de estados, foi usado a biblioteca Python, control, essa biblioteca permite criar um sistema no espaço de estados a partir das matrizes A, B, C, D +

+
+ +

Obtendo a Função de Transferência a partir do Espaço de Estados

+
+

+Para obter a função de transferência a partir do sistema no espaço de estados, a biblioteca control implementa uma função, ct.ss2tf(sys), que recebe como parâmetro, o sistema no espaço de estados e retorna a função de transferência. +

+
+ +

Informações do sistema em malha aberta

+
+

+Antes de realizar a simulação em malha aberta, é interessante observar as características do sistema, para isso, a biblioteca control implementa algumas função. +

+
+

Explicando as diferentes funções da biblioteca control

+
+

+A função ct.step_info() recebe como parâmetro o sistema no espaço de estados ou uma função de transferência e retorna as características do sistema, para esse exemplo, ao aplicar a função ela retorna diversas características, exemplo: +

+
+
    +
  • +Tempo de acomodação -> ‘SettlingTime’: 10.308519357198815’ +
  • +
  • +Ultrapassagem Percentual -> ‘Overshoot’: 69.54106137593485, +
  • +
  • +Tempo de Subida -> ‘RiseTime’: 0.396481513738416 +
  • +
+ +

saída:

+
{'RiseTime': 0.396481513738416,
+ 'SettlingTime': 10.308519357198815,
+ 'SettlingMin': 0.14343794449344063,
+ 'SettlingMax': 0.47415111647086844,
+ 'Overshoot': 69.54106137593485,
+ 'Undershoot': 0,
+ 'Peak': 0.47415111647086844,
+ 'PeakTime': 1.0308519357198815,
+ 'SteadyStateValue': 0.2796674225245654}
+
+

+A função ct.damp() recebe como argumento o sistema no espaço de estados ou a função de transferência e retorna os Autovalores, amortecimento e frequência natural para cada polo do sistema. +

+
+ +

saída:

+
_____Eigenvalue______ Damping___ Frequency_
+   -0.3585    +3.139j     0.1135       3.16
+   -0.3585    -3.139j     0.1135       3.16
+
+

+A função ct.poles() recebe como argumento o sistema no espaço de estados ou a função de transferência e retorna os polos do sistema, para esse caso o sistema é de segunda ordem, pois possui dois pólos. +

+
+ +

saída:

+
array([-0.35849057+3.13948884j, -0.35849057-3.13948884j])
+
+

+A função ct.zeros() recebe como argumento o sistema no espaço de estados ou a função de transferência e retorna os zeros do sistema. para esse caso o sistema não possui zeros. +

+
+ +

saída:

+
array([], dtype=float64)
+

Resposta ao degrau

+ +

Saída:

+
+
+

+
+
+



+

Controlador projetado usando LGR com auxílio do Matlab

+
+

+Para fins de teste foi projetado um controlador simples usando o matlab e encontrada a função de transferência com o auxílio da biblioteca Control, por fim foi obtida a equação de diferenças para implementar o controlador no simulador. +

+
+
+
+ +

+Figura 6 - Diagrama de blocos do Sistema em Malha Fechada. +

+
+
+

Função de Transferência do Controlador

+

\[ +\begin{align} +C(s) &= \frac{0,2126s + 0,7893}{s} \tag{13} +\end{align} +\]

+

Função de Transferência do Controlador usando a biblioteca Control do Python

+ +

saída:

+

\[ +\dfrac{0.2126 s + 0.7893}{s} +\]

+

Simulação do Sistema em Malha Fechada

+ +

saída:

+

\[ +\dfrac{0.5937s+2.204}{s^3 +0.717s^2+10.58s+2.204} +\]

+

Resposta ao degrau unitário

+ +

saída:

+
+
+

+
+
+
+

+Ao analisar o sistema com o controlador, temos que o sistema não possui erro em regime permanente e seu overshoot é zero, no entanto, para que esses requisitos fossem obtidos ouve um aumento no tempo de acomodação. +

+
+


+

Função de Transferência Discreta C(z)

+
+

+Para discretizar o sistema foi usado um período de amostragem de 0,01s. +

+
+ +

\[ +\dfrac{0.2165 z + 0.2087}{z-1} \quad dt = 0.01 +\]

+

\[ +\begin{align} + C(z) &= \dfrac{0,2165z −0,2087}{z-1} \tag{14}\\ + &= \dfrac{0,2165z −0,2087}{z-1} \cdot \dfrac{z^{-1}}{z^{-1}} \tag{15}\\ + &= \dfrac{0,2165 − 0,2087z^{-1}}{1-z^{-1}} \tag{16}\\ +\end{align} +\]

+

Encontrando a equação de diferenças do controlador

+

\[ +\begin{align} +C(z) &= \dfrac{U(z)}{E(z)} \tag{20} +\end{align} +\]

+

onde:

+

\[ +\begin{align} + U(z) &= Z\{u[k]\} \tag{17}\\ + E(z) &= Z\{e[k]\} \tag{18}\\ + \dfrac{U(z)}{E(z)} &= \dfrac{0,2165 − 0,2087z^{-1}}{1-z^{-1}} \tag{19}\\ + (1-z^{-1})U(z) &= (0,2165 − 0,2087z^{-1})E(z) \tag{20}\\ + U(z)-z^{-1}U(z) &= 0,2165E(z) − 0,2087z^{-1}E(z) \tag{21}\\ + Z^{-1}\{U(z)-z^{-1}U(z)\} &= Z^{-1}\{0,2165E(z) − 0,2087z^{-1}E(z)\} \tag{22}\\ + u[k] − u[k − 1] &= 0,2165e[k] − 0,2087e[k − 1] \tag{23}\\ + u[k] &= u[k − 1] + 0,2165e[k] − 0,2087e[k − 1] \tag{24} +\end{align} +\]

+
+

+Agora é possível implementar uma classe python para o controlador a partir da equação de diferenças. +

+
+

\[ +\begin{align} + u[k] &= u[k − 1] + 0,2165e[k] − 0,2087e[k − 1] \tag{25} +\end{align} +\]

+
+

+com a função de diferenças encontrada, agora é possível implementa-la usando python e fecha a malha com o controlador para simular, essa lógica está implementada no simulador. +

+
+



+

Referências

+
+

+

+
+[1.] JOB, Mila Mary; JOSE, P. Subha Hency. Modeling and control of mechatronic aeropendulum. In: 2015 International Conference on Innovations in Information, Embedded and Communication Systems (ICIIECS). IEEE, 2015. p. 1-5. +
+


+
+[2.] Silva. Yago. Projeto, construção e controle de um aeropêndulo . Centro de Engenharia Elétrica e Informática, Departamento de Engenharia Elétrica e Informática, Universidade Federal de Campina Grande - UFCG, 2018. +
+


+
+[3.] MOHAMMADBAGHERI, Amin; YAGHOOBI, Mahdi. A new approach to control a driven pendulum with PID method. In: 2011 UkSim 13th International Conference on Computer Modelling and Simulation. IEEE, 2011. p. 207-211. +
+


+
+[4.] SILVA, Yago Luiz Monteiro et al. Projeto, construção e controle de um aeropêndulo. 2018. +
+
+

+
+
+
+
+ + + + diff --git a/simulacao_modelagem_aeropendulo/animacao_aeropendulo.py b/simulacao_modelagem_aeropendulo/animacao_aeropendulo.py deleted file mode 100644 index 5a1e896..0000000 --- a/simulacao_modelagem_aeropendulo/animacao_aeropendulo.py +++ /dev/null @@ -1,111 +0,0 @@ -# ----------------------------------------------------- -# Universidade Federal do Pará -# Campus Universitário de Tucuruí -# Faculdade de Engenharia Elétrica -# ----------------------------------------------------- -# -# Laboratório Virtual Sistemas Dinâmicos e Controle -# Tema: Simulação Aeropêndulo -# Autor: Oséias Farias -# Orientadores: Prof. Dr: Raphael Teixeira, -# Prof. Dr: Rafael Bayma -# ---------------------------------------------------- -# -import vpython as vp - - -class AnimacaoAeropendulo: - """ - Classe que implementa a aminação do Aeropêndulo. - - Args: - comprimento_braco: tamanho do braço do Aeropêndulo. - """ - def __init__(self, comprimento_braco=4.4) -> None: - # Parâmetros do Aeropêndulo - self.comprimento_braco = comprimento_braco - self.scene = vp.canvas(title="

Aeropêndulo

", - width=650, - height=580, align="left", autoscale=0, range=5, - center=vp.vec(0, 3, 0), - background=vp.vector(1.7, 0.7, 0.9), - color=vp.vec(1, 0.6, 0.6), - forward=vp.vec(-0.3, 0, -1)) - # chamando a função para criar a aminação gráfica do Aeropêndulo. - self.aeropendulo = self.__aminacao() - - def __aminacao(self) -> vp.compound: - """ - Classe que implementa o Aeropêndulo. - - Args: - comprimento_braco: tamanho do braço do Aeropêndulo. - Returns: - Retorna um objeto (vpython) que contêm a estrutura do Aeropêndulo. - """ - self.base = vp.box(pos=vp.vec(0, -0.85, 0), size=vp.vec(30, 0.2, 15), - texture=vp.textures.wood) - self.parede = vp.box(pos=vp.vec(0, 7.1, -7.55), - size=vp.vec(30, 16, 0.2), - color=vp.vec(0.1, 0.1, 0.1), shininess=0.05) - self.sitio = vp.text(pos=vp.vec(0, 8.1, -7.45), - text="AEROPÊNDULO", color=vp.vec(1, 0.6, 0.6), - align='center', depth=0) - - # Braço do Aeropêndulo. - self.barra = vp.box(pos=vp.vec(0, -1.4, 0), - size=vp.vec(0.2, self.comprimento_braco, 0.2), - color=vp.vec(0.5, 0.5, 0.95)) - - # Base que acopla o motor ao braço. - self.base_motor = vp.cylinder(pos=vp.vec(-0.2, -4, 0), radius=0.4, - axis=vp.vec(0.4, 0, 0), - color=vp.vec(0.5, 0.5, 0.95)) - # Armadura do motor. - self.base2_motor = vp.box(pos=vp.vec(0.4, -4, 0), - size=vp.vec(0.4, 0.4, 0.4), - color=vp.vec(1, 1, 0)) - - # Eixo que da hélice do motor - self.base_helice = vp.cylinder(pos=vp.vec(0.4, -4, 0), radius=0.05, - axis=vp.vec(0.4, 0, 0), - color=vp.vec(0.5, 0.5, 0.8)) - - # Hélice. - self.helice = vp.box(pos=vp.vec(0.8, -4, 0), - size=vp.vec(0.05, 0.2, 2), - color=vp.vec(1, 1, 0)) - - # Motor completo. - self.motor = vp.compound([self.base_motor, - self.base2_motor, - self.base_helice]) - - # Motor + Hélice. - self.motor_helice = vp.compound([self.motor, self.helice]) - - # Aeropêndulo - self.pendulo = vp.compound([self.barra, self.motor_helice]) - self.pendulo.pos = vp.vec(0.31, 2.7, 0) - - # Eixo de sustentação. - self.eixo = vp.cylinder(pos=vp.vec(0, 5.2, 0.3), radius=0.09, - axis=vp.vec(0, 0, -2), - color=vp.vec(0.7, 0.4, 0.1)) - - # Estrutura de sustentação do aeropêndulo. - self.b1 = vp.box(pos=vp.vec(0, 1.7, -2), size=vp.vec(3, 8, 0.6), - color=vp.vec(0.8, 0.8, 0.8)) - - self.b2 = vp.box(pos=vp.vec(0, -0.6, -1.5), size=vp.vec(4.5, 0.4, 2.5), - color=vp.vec(0.8, 0.8, 0.8)) - - self.logo = vp.box(pos=vp.vec(0, 2.5, -1.7), - texture="https://i.imgur.com/odcLHxB.png", - size=vp.vec(2, 2, 0.2)) - - self.ufpa = vp.text(pos=vp.vec(0, 3.7, -1.7), text="UFPA", - color=vp.vec(1, 0.6, 0.6), height=0.5, - align='center', depth=0) - - return self.pendulo diff --git a/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo copy.drawio b/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo copy.drawio new file mode 100644 index 0000000..3d3f989 --- /dev/null +++ b/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo copy.drawio @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo copy.png b/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo copy.png new file mode 100644 index 0000000..5ba8cd0 Binary files /dev/null and b/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo copy.png differ diff --git a/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo.drawio b/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo.drawio new file mode 100644 index 0000000..9a7d302 --- /dev/null +++ b/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo.drawio @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo.png b/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo.png new file mode 100644 index 0000000..482874c Binary files /dev/null and b/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo.png differ diff --git a/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo.svg b/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo.svg new file mode 100644 index 0000000..a273692 --- /dev/null +++ b/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo.svg @@ -0,0 +1 @@ +
animacao_aeropendulo.py
animacao_aeropendulo.py
graficos_aeropendulo.py
graficos_aeropendulo.py
implementacao_controlador.py
implementacao_controlador.py
interface_interativa.py
interface_interativa.py
modelo_mat_aeropendulo.py
modelo_mat_aeropendulo.py
main.py
main.py
Text is not SVG - cannot display
\ No newline at end of file diff --git a/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo1.png b/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo1.png new file mode 100644 index 0000000..7e5f8fc Binary files /dev/null and b/simulacao_modelagem_aeropendulo/diagramas/diagrama_estrutura_codigo1.png differ diff --git a/simulacao_modelagem_aeropendulo/graficos_aeropendulo.py b/simulacao_modelagem_aeropendulo/graficos_aeropendulo.py deleted file mode 100644 index c2a3a38..0000000 --- a/simulacao_modelagem_aeropendulo/graficos_aeropendulo.py +++ /dev/null @@ -1,58 +0,0 @@ -# ----------------------------------------------------- -# Universidade Federal do Pará -# Campus Universitário de Tucuruí -# Faculdade de Engenharia Elétrica -# ----------------------------------------------------- -# -# Laboratório Virtual Sistemas Dinâmicos e Controle -# Tema: Simulação Aeropêndulo -# Autor: Oséias Farias -# Orientadores: Prof. Dr: Raphael Teixeira, -# Prof. Dr: Rafael Bayma -# ---------------------------------------------------- -# -import vpython as vp -from typing import Tuple - - -class Graficos: - """ - Gráfico para polagem dos dados dos estados do Aeroèndulo. - - """ - def __init__(self): - ... - - def graficos(self) -> Tuple: - """ - Método que cria os Gráfico. - - Returns: - Retorna uma tupla contendo o objeto do gráfico e da curvas. - """ - titulo = "Gráficos dos estados do Aeropêndulo" - self.grafico = vp.graph(title=titulo, align="right", - xtitle='tempo (s)', fast=True, width=650, - height=450, center=vp.vector(0, 12, 0), - scroll=True, xmin=0, xmax=5, ymin=-5, ymax=5, - dot=True, background=vp.vector(0.95, - 0.95, 0.95)) - - self.curva1 = vp.gcurve(color=vp.color.blue, width=3, - markers=False, label="Posição Angular", - dot=True, dot_color=vp.color.blue) - - self.curva2 = vp.gcurve(color=vp.color.red, width=3, markers=False, - label="Velocidade Angular", - dot=True, dot_color=vp.color.red) - - # curva3 = vp.gcurve(color=vp.color.orange, width=3, markers=False, - # label="Aceleração Angular do Pêndulo", - # dot=True, dot_color=vp.color.orange) - return self.grafico, self.curva1, self.curva2 - - def reset(self): - self.curva1.delete() - self.curva2.delete() - self.grafico.xmin = 0 - self.grafico.xmax = 5 diff --git a/simulacao_modelagem_aeropendulo/main.py b/simulacao_modelagem_aeropendulo/main.py index c722cc7..73a6d8f 100644 --- a/simulacao_modelagem_aeropendulo/main.py +++ b/simulacao_modelagem_aeropendulo/main.py @@ -9,74 +9,89 @@ # Autor: Oséias Farias # Orientadores: Prof. Dr: Raphael Teixeira, # Prof. Dr: Rafael Bayma +# +# Data: 2023 # ---------------------------------------------------- # + import vpython as vp -from graficos_aeropendulo import Graficos -from animacao_aeropendulo import AnimacaoAeropendulo -from modelo_mat_aeropendulo import ModeloMatAeropendulo +import numpy as np +from aeropendulo import (Graficos, AnimacaoAeropendulo, + Interface, ModeloMatAeropendulo, + ControladorDiscreto) -# Instanciando um objeto AeropenduloAaeropendulo = Aeropendulo() +# Instanciando um objeto AeropenduloAaeropendulo() animacao_aeropendulo = AnimacaoAeropendulo() -# ############# INICIO SESSÃO - TESTE MUNU INTERATIVO ############## -animacao_aeropendulo.scene.append_to_caption("\tMenu Interativo Aeropêndulo\n") -animacao_aeropendulo.scene.append_to_caption("\tRefazer Simulação\n\n") - - -def Reset(): - global x, t, t_ant - g.reset() - y = animacao_aeropendulo.aeropendulo.axis.y - # y1 = animacao_aeropendulo.aeropendulo.pos.y - animacao_aeropendulo.aeropendulo.rotate(axis=vp.vec(0, 0, 1), - angle=-0.5 - y, - origin=vp.vec(0, 5.2, 0)) - animacao_aeropendulo.aeropendulo.axis = axis_init - animacao_aeropendulo.aeropendulo.pos = pos_init - # Reiniciar simulação - x = [0.0, -0.5] - t = 0.0 - t_ant = 0.0 - - -animacao_aeropendulo.scene.append_to_caption("\t ") -vp.button(bind=Reset, text="Reset", - color=vp.color.white, - background=vp.color.red) -animacao_aeropendulo.scene.append_to_caption("\n\n\n") - -# ############# FIM SESSÃO - TESTE MUNU INTERATIVO ############## - # Instanciando um objeto para plotagem dos gráficos dinâmicos dos # estados do Aeropêndulo g = Graficos() -graf, plot1, plot2 = g.graficos() +graf, plot1, plot2, plot3, plot4 = g.graficos() # Instânciando um objeto para solução matemática do sistema Aeropêndulo. -mma = ModeloMatAeropendulo() +Km = 0.0296 +m = 0.36 +d = 0.03 +J = 0.0106 +c = 0.0076 +mma = ModeloMatAeropendulo(K_m=Km, m=m, d=d, J=J, c=c) + +# Instânciando um objeto ControladorDiscreto +controlador = ControladorDiscreto(referencia=0.01) +u = 0 # Sinal de controle inicial + +# Instanciando um objeto Interface +interface = Interface(animacao_aeropendulo, controlador) ts = 1e-2 # Condições Iniciais dos estados -x = [0.0, -0.5] +x = np.array([0.0, 0.0]) t = 0.0 t_ant = 0.0 -# salvando as condições iniciais dos axis pos do aeropêndulo -axis_init = animacao_aeropendulo.aeropendulo.axis -pos_init = animacao_aeropendulo.aeropendulo.pos +# Simulação do Sistema +while True: + vp.rate(100) + if interface.EXE: + # Calcula as derivadas do sitema + dx = mma.modelo_aeropendulo(x, t) + dt = t - t_ant + # Atualização dos estados + x = x + dt * dx -while True: - vp.rate(70) - dx = mma.modelo_aeropendulo(x, t) - dt = t - t_ant - x = x + dt * dx - - t_ant = t - t += ts - animacao_aeropendulo.aeropendulo.rotate(axis=vp.vec(0, 0, 1), - angle=x[1]*ts, - origin=vp.vec(0, 5.2, 0)) - plot1.plot(t, x[0]) - plot2.plot(t, x[1]) + # Pega o Ângulo e envia para o controlador (Realimentação do sistema) + controlador.set_sensor(x[1]) + + # O controlador calcula o sinal de controle + controlador.control_pi() + + # Controle proporcional + # controlador.controle_proporcional(kp=10.0) + # pega o sinal de controle calculado e salva na variável u + u = controlador.get_u() + + # Sinal de controle aplicado a entrada do sistema + mma.set_u(u) + + # print(x[1]*(180/np.pi)) + t_ant = t + t += ts + + # Atualiza o ângulo do Aeropêndulo + animacao_aeropendulo.aeropendulo.rotate(axis=vp.vec(0, 0, 1), + angle=x[0]*ts, + origin=vp.vec(0, 5.2, 0)) + + # Animação da dinâmica da Hélice + animacao_aeropendulo.update_helice(x[0], ts) + + print(x[1] + interface.valor_angle) + # Gráfico do ângulo. + plot1.plot(t, x[1] + interface.valor_angle) + # Gráfico do sinal de referência + plot2.plot(t, controlador.r + interface.valor_angle) + # Gráfico da velocidade ângular. + plot3.plot(t, x[0]) + # Gráfico do sinal de controle + plot4.plot(t, u) diff --git a/simulacao_modelagem_aeropendulo/projeto_de_controladores/projeto_controlador_por_lgr/ControlSystemDesignerSession1.mat b/simulacao_modelagem_aeropendulo/projeto_de_controladores/projeto_controlador_por_lgr/ControlSystemDesignerSession1.mat new file mode 100644 index 0000000..2723704 Binary files /dev/null and b/simulacao_modelagem_aeropendulo/projeto_de_controladores/projeto_controlador_por_lgr/ControlSystemDesignerSession1.mat differ diff --git a/simulacao_modelagem_aeropendulo/projeto_de_controladores/projeto_controlador_por_lgr/ControlSystemDesignerSession2.mat b/simulacao_modelagem_aeropendulo/projeto_de_controladores/projeto_controlador_por_lgr/ControlSystemDesignerSession2.mat new file mode 100644 index 0000000..014d154 Binary files /dev/null and b/simulacao_modelagem_aeropendulo/projeto_de_controladores/projeto_controlador_por_lgr/ControlSystemDesignerSession2.mat differ diff --git a/simulacao_modelagem_aeropendulo/projeto_de_controladores/projeto_controlador_por_lgr/projeto_controlador_lgr.m b/simulacao_modelagem_aeropendulo/projeto_de_controladores/projeto_controlador_por_lgr/projeto_controlador_lgr.m new file mode 100644 index 0000000..0074005 --- /dev/null +++ b/simulacao_modelagem_aeropendulo/projeto_de_controladores/projeto_controlador_por_lgr/projeto_controlador_lgr.m @@ -0,0 +1,14 @@ +% Projeto de controlador por LGR +clear all; close all; clc + +num = [2.792] +den = [1, 0.717, 9.985] + +Gs = tf(num, den) + +rlocus(Gs) +grid on + +% projeto por lgr + +% sisotool(Gs) diff --git a/simulacao_modelagem_aeropendulo/utils/Template_Dissertacao_NDAE.docx b/simulacao_modelagem_aeropendulo/utils/Template_Dissertacao_NDAE.docx new file mode 100644 index 0000000..d486cb7 Binary files /dev/null and b/simulacao_modelagem_aeropendulo/utils/Template_Dissertacao_NDAE.docx differ diff --git a/simulacao_modelagem_aeropendulo/utils/Template_TCC_CAMTUC.docx b/simulacao_modelagem_aeropendulo/utils/Template_TCC_CAMTUC.docx new file mode 100644 index 0000000..b143746 Binary files /dev/null and b/simulacao_modelagem_aeropendulo/utils/Template_TCC_CAMTUC.docx differ diff --git a/simulacao_modelagem_aeropendulo/utils/aeropendulo.png b/simulacao_modelagem_aeropendulo/utils/aeropendulo.png deleted file mode 100644 index 1970894..0000000 Binary files a/simulacao_modelagem_aeropendulo/utils/aeropendulo.png and /dev/null differ diff --git a/simulacao_modelagem_aeropendulo/utils/aeropendulo_1.png b/simulacao_modelagem_aeropendulo/utils/aeropendulo_1.png new file mode 100644 index 0000000..280346f Binary files /dev/null and b/simulacao_modelagem_aeropendulo/utils/aeropendulo_1.png differ diff --git a/simulacao_modelagem_aeropendulo/utils/demo_gif.gif b/simulacao_modelagem_aeropendulo/utils/demo_gif.gif new file mode 100644 index 0000000..c1f164b Binary files /dev/null and b/simulacao_modelagem_aeropendulo/utils/demo_gif.gif differ diff --git a/simulacao_modelagem_aeropendulo/utils/diagrama_bloco_aeropendulo_nao_linear.drawio b/simulacao_modelagem_aeropendulo/utils/diagrama_bloco_aeropendulo_nao_linear.drawio new file mode 100644 index 0000000..1a48402 --- /dev/null +++ b/simulacao_modelagem_aeropendulo/utils/diagrama_bloco_aeropendulo_nao_linear.drawio @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/simulacao_modelagem_aeropendulo/utils/diagrama_bloco_aeropendulo_nao_linear.svg b/simulacao_modelagem_aeropendulo/utils/diagrama_bloco_aeropendulo_nao_linear.svg new file mode 100644 index 0000000..603b478 --- /dev/null +++ b/simulacao_modelagem_aeropendulo/utils/diagrama_bloco_aeropendulo_nao_linear.svg @@ -0,0 +1 @@ +
\(\df...
\(c\)
\(mgL\)
\(\dfrac...
\(x_1\)
\(\theta\)
\(V\)
\(\dot{x}_1\)
\(\df...
sen
sen
\(\dot{x}_2\)
\(J\)
\(K_m\)
\(x_2\)
\(-\)
\(+\)
\(+\)
\(+\)
Text is not SVG - cannot display
\ No newline at end of file diff --git a/simulacao_modelagem_aeropendulo/utils/favicon_aeropendulo_png.png b/simulacao_modelagem_aeropendulo/utils/favicon_aeropendulo_png.png new file mode 100644 index 0000000..c79f3da Binary files /dev/null and b/simulacao_modelagem_aeropendulo/utils/favicon_aeropendulo_png.png differ diff --git a/simulacao_modelagem_aeropendulo/utils/gsinal.png b/simulacao_modelagem_aeropendulo/utils/gsinal.png deleted file mode 100644 index b6a3407..0000000 Binary files a/simulacao_modelagem_aeropendulo/utils/gsinal.png and /dev/null differ diff --git a/simulacao_modelagem_aeropendulo/utils/lab_virtual.png b/simulacao_modelagem_aeropendulo/utils/lab_virtual.png new file mode 100644 index 0000000..910c5db Binary files /dev/null and b/simulacao_modelagem_aeropendulo/utils/lab_virtual.png differ diff --git a/simulacao_modelagem_aeropendulo/utils/logo_ufpa.png b/simulacao_modelagem_aeropendulo/utils/logo_ufpa.png new file mode 100644 index 0000000..9051e6c Binary files /dev/null and b/simulacao_modelagem_aeropendulo/utils/logo_ufpa.png differ diff --git a/simulacao_modelagem_aeropendulo/utils/sc.png b/simulacao_modelagem_aeropendulo/utils/sc.png deleted file mode 100644 index 6877e26..0000000 Binary files a/simulacao_modelagem_aeropendulo/utils/sc.png and /dev/null differ diff --git a/simulacao_modelagem_aeropendulo/utils/simu_malha_aberta.svg b/simulacao_modelagem_aeropendulo/utils/simu_malha_aberta.svg new file mode 100644 index 0000000..7c7a081 --- /dev/null +++ b/simulacao_modelagem_aeropendulo/utils/simu_malha_aberta.svg @@ -0,0 +1,1563 @@ + + + + + + + + 2023-03-31T01:27:07.747287 + image/svg+xml + + + Matplotlib v3.7.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/simulacao_modelagem_aeropendulo/utils/simu_malha_fechada.svg b/simulacao_modelagem_aeropendulo/utils/simu_malha_fechada.svg new file mode 100644 index 0000000..e5eee33 --- /dev/null +++ b/simulacao_modelagem_aeropendulo/utils/simu_malha_fechada.svg @@ -0,0 +1,1544 @@ + + + + + + + + 2023-03-31T01:26:04.945423 + image/svg+xml + + + Matplotlib v3.7.1, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/simulacao_modelagem_aeropendulo/utils/simulacao.png b/simulacao_modelagem_aeropendulo/utils/simulacao.png index 6d20d23..64f9065 100644 Binary files a/simulacao_modelagem_aeropendulo/utils/simulacao.png and b/simulacao_modelagem_aeropendulo/utils/simulacao.png differ diff --git a/simulacao_modelagem_aeropendulo/utils/sistema_aeropendulo_malha_fechada.drawio b/simulacao_modelagem_aeropendulo/utils/sistema_aeropendulo_malha_fechada.drawio new file mode 100644 index 0000000..bba7c8c --- /dev/null +++ b/simulacao_modelagem_aeropendulo/utils/sistema_aeropendulo_malha_fechada.drawio @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/simulacao_modelagem_aeropendulo/utils/sistema_aeropendulo_malha_fechada.svg b/simulacao_modelagem_aeropendulo/utils/sistema_aeropendulo_malha_fechada.svg new file mode 100644 index 0000000..de4f2d0 --- /dev/null +++ b/simulacao_modelagem_aeropendulo/utils/sistema_aeropendulo_malha_fechada.svg @@ -0,0 +1 @@ +
\(\theta\)
\(\theta\)
\(C(s)\)
\(-\)
\(+\)
\(G(s)\)
Planta / Sistema
Planta / Sistema
Controlador
Controlador
Referência 
Referência 
Posição ângular do Aeropêndulo
Posição ângular do Aeropêndulo
\(V\)
Sinal de Controle
Sinal de Controle
\(E(s)\)
Sinal de Erro
Sinal de Erro
Realimentação
(Sinal do sendor de Ângulo)
Realimentação...
Text is not SVG - cannot display
\ No newline at end of file