Skip to content
Snippets Groups Projects
Commit b47f1f2f authored by Peter Gerwinski's avatar Peter Gerwinski
Browse files

Vorbereitungen 17.12.2020, Praktikumsversuch 2

parent bbbbb237
No related branches found
No related tags found
No related merge requests found
Showing
with 2125 additions and 4 deletions
No preview for this file type
......@@ -160,10 +160,12 @@
die Dicke eines Blatts Papier messen. Beides ist jedoch möglich.
\item
\textbf{Abgabe}
\textbf{Abgabe:}
Ihre Quelltexte mit den Lösungen der Praktikumsaufgabe schicken Sie bitte
per E-Mail an \file{peter.gerwinski@hs-bochum.de}
mit dem \textbf{Betreff:} \lstinline[style=terminal]{fi2niNoh}.
mit dem \textbf{Betreff:} \lstinline[style=terminal]{fi2niNoh}
unter Angabe von Name, Matrikel-Nummer,
Studiengang (MI/MP/TI) und Studienmodell (KIA/KIS/GS).
\end{itemize}
......@@ -181,7 +183,7 @@
\setlength{\leftskip}{3cm}
Stand: 26.\ November 2020
Stand: 17.\ Dezember 2020
% Soweit nicht anders angegeben:\\
Copyright \copyright\ 2014, 2015, 2016, 2017, 2018, 2019, 2020\quad Peter Gerwinski\\
......
......@@ -20,7 +20,7 @@
% Attribution-ShareAlike 3.0 Unported License along with this
% document. If not, see <http://creativecommons.org/licenses/>.
% README: Parameter des Hauptprogramms, String-Operationen
% README: Präprozessor, Bibliotheken einbinden und verwenden
\documentclass[10pt,t]{beamer}
......
#include <gtk/gtk.h>
#define WIDTH 320
#define HEIGHT 240
double t = 0.0;
double dt = 0.2;
int r = 5;
double x = 10;
double y = 200;
double vx = 20;
double vy = -60;
double g = 9.81;
gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
{
GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
gdk_cairo_set_source_rgba (c, &blue);
cairo_arc (c, x, y, r, 0, 2 * G_PI);
cairo_fill (c);
return FALSE;
}
gboolean timer (GtkWidget *widget)
{
t += dt;
x += vx * dt;
y += vy * dt;
vx = vx;
vy = 0.5 * g * (t * t);
if (y + r >= HEIGHT)
vy = -vy * 0.9;
if (x + r >= WIDTH)
vx = -vx * 0.9;
if (x - r <= 0)
vx = -vx * 0.9;
gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, widget);
return FALSE;
}
int main (int argc, char **argv)
{
gtk_init (&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_show (window);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
GtkWidget *drawing_area = gtk_drawing_area_new ();
gtk_widget_show (drawing_area);
gtk_container_add (GTK_CONTAINER (window), drawing_area);
gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
gtk_main ();
return 0;
}
#include <gtk/gtk.h>
#define WIDTH 320
#define HEIGHT 240
double x = 5;
double y = 95;
double vx = 0.5;
double vy = 0.7;
double dt = 0.05;
double g = 9.81;
gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
{
GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
gdk_cairo_set_source_rgba (c, &blue);
cairo_arc (c, x, HEIGHT - y, 5, 0, 2 * G_PI);
cairo_fill (c);
return FALSE;
}
gboolean timer (GtkWidget *widget)
{
x += vx * dt;
y += vy * dt;
vx += 0.0 * dt;
vy += (-g) * dt;
gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, widget);
return FALSE;
}
int main (int argc, char **argv)
{
gtk_init (&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add (GTK_CONTAINER (window), vbox);
GtkWidget *button = gtk_button_new_with_label ("Quit");
g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
gtk_container_add (GTK_CONTAINER (vbox), button);
GtkWidget *drawing_area = gtk_drawing_area_new ();
gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, drawing_area);
gtk_widget_show (drawing_area);
gtk_widget_show (button);
gtk_widget_show (vbox);
gtk_widget_show (window);
gtk_main ();
return 0;
}
#include <gtk/gtk.h>
#define WIDTH 640
#define HEIGHT 480
double x = 5;
double y = 95;
double vx = 0.5;
double vy = 0.7;
double dt = 0.05;
double g = 9.81;
gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
{
GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
gdk_cairo_set_source_rgba (c, &blue);
cairo_arc (c, x, HEIGHT - y, 5, 0, 2 * G_PI);
cairo_fill (c);
return FALSE;
}
gboolean timer (GtkWidget *widget)
{
x += vx * dt;
y += vy * dt;
vx += 0.0 * dt;
vy += (-g) * dt;
gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, widget);
return FALSE;
}
int main (int argc, char **argv)
{
gtk_init (&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add (GTK_CONTAINER (window), vbox);
GtkWidget *button = gtk_button_new_with_label ("Quit");
g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
gtk_container_add (GTK_CONTAINER (vbox), button);
GtkWidget *drawing_area = gtk_drawing_area_new ();
gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, drawing_area);
gtk_widget_show (drawing_area);
gtk_widget_show (button);
gtk_widget_show (vbox);
gtk_widget_show (window);
gtk_main ();
return 0;
}
#include <gtk/gtk.h>
#define WIDTH 640
#define HEIGHT 480
double x = 5;
double y = 95;
double vx = 5.0;
double vy = 0.7;
double dt = 0.05;
double g = 9.81;
gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
{
GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
gdk_cairo_set_source_rgba (c, &blue);
cairo_arc (c, x, HEIGHT - y, 5, 0, 2 * G_PI);
cairo_fill (c);
return FALSE;
}
gboolean timer (GtkWidget *widget)
{
x += vx * dt;
y += vy * dt;
vx += 0.0 * dt;
vy += (-g) * dt;
gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, widget);
return FALSE;
}
int main (int argc, char **argv)
{
gtk_init (&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add (GTK_CONTAINER (window), vbox);
GtkWidget *button = gtk_button_new_with_label ("Quit");
g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
gtk_container_add (GTK_CONTAINER (vbox), button);
GtkWidget *drawing_area = gtk_drawing_area_new ();
gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, drawing_area);
gtk_widget_show (drawing_area);
gtk_widget_show (button);
gtk_widget_show (vbox);
gtk_widget_show (window);
gtk_main ();
return 0;
}
#include <gtk/gtk.h>
#define WIDTH 640
#define HEIGHT 480
double x = 5;
double y = 95;
double vx = 50.0;
double vy = 0.7;
double dt = 0.05;
double g = 9.81;
gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
{
GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
gdk_cairo_set_source_rgba (c, &blue);
cairo_arc (c, x, HEIGHT - y, 5, 0, 2 * G_PI);
cairo_fill (c);
return FALSE;
}
gboolean timer (GtkWidget *widget)
{
x += vx * dt;
y += vy * dt;
vx += 0.0 * dt;
vy += (-g) * dt;
gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, widget);
return FALSE;
}
int main (int argc, char **argv)
{
gtk_init (&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add (GTK_CONTAINER (window), vbox);
GtkWidget *button = gtk_button_new_with_label ("Quit");
g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
gtk_container_add (GTK_CONTAINER (vbox), button);
GtkWidget *drawing_area = gtk_drawing_area_new ();
gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, drawing_area);
gtk_widget_show (drawing_area);
gtk_widget_show (button);
gtk_widget_show (vbox);
gtk_widget_show (window);
gtk_main ();
return 0;
}
#include <gtk/gtk.h>
#define WIDTH 640
#define HEIGHT 480
#define RADIUS 5
double x = 5;
double y = 95;
double vx = 50.0;
double vy = 70.0;
double dt = 0.05;
double g = 9.81;
gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
{
GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
gdk_cairo_set_source_rgba (c, &blue);
cairo_arc (c, x, HEIGHT - y, RADIUS, 0, 2 * G_PI);
cairo_fill (c);
return FALSE;
}
gboolean timer (GtkWidget *widget)
{
x += vx * dt;
y += vy * dt;
vx += 0.0 * dt;
vy += (-g) * dt;
if (x + RADIUS >= WIDTH)
vx = -vx;
gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, widget);
return FALSE;
}
int main (int argc, char **argv)
{
gtk_init (&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add (GTK_CONTAINER (window), vbox);
GtkWidget *button = gtk_button_new_with_label ("Quit");
g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
gtk_container_add (GTK_CONTAINER (vbox), button);
GtkWidget *drawing_area = gtk_drawing_area_new ();
gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, drawing_area);
gtk_widget_show (drawing_area);
gtk_widget_show (button);
gtk_widget_show (vbox);
gtk_widget_show (window);
gtk_main ();
return 0;
}
#include <gtk/gtk.h>
#define WIDTH 320
#define HEIGHT 240
double x = 5;
double y = 95;
double vx = 0.5;
double vy = 0.7;
double dt = 0.05;
double g = 9.81;
gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
{
GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
gdk_cairo_set_source_rgba (c, &blue);
cairo_arc (c, x, y, 5, 0, 2 * G_PI);
cairo_fill (c);
return FALSE;
}
gboolean timer (GtkWidget *widget)
{
x += vx * dt;
y += vy * dt;
vx += 0.0 * dt;
vy += (-g) * dt;
gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, widget);
return FALSE;
}
int main (int argc, char **argv)
{
gtk_init (&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
GtkWidget *vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add (GTK_CONTAINER (window), vbox);
GtkWidget *button = gtk_button_new_with_label ("Quit");
g_signal_connect (button, "clicked", G_CALLBACK (gtk_main_quit), NULL);
gtk_container_add (GTK_CONTAINER (vbox), button);
GtkWidget *drawing_area = gtk_drawing_area_new ();
gtk_container_add (GTK_CONTAINER (vbox), drawing_area);
g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);
gtk_widget_set_size_request (drawing_area, 100, 100);
g_timeout_add (50, (GSourceFunc) timer, drawing_area);
gtk_widget_show (drawing_area);
gtk_widget_show (button);
gtk_widget_show (vbox);
gtk_widget_show (window);
gtk_main ();
return 0;
}
File added
This diff is collapsed.
File added
% hp-2020ws-p2.pdf - Labor Notes on Low-Level Programming
% Copyright (C) 2014, 2015, 2018, 2019, 2020 Peter Gerwinski
%
% This document is free software: you can redistribute it and/or
% modify it either under the terms of the Creative Commons
% Attribution-ShareAlike 3.0 License, or under the terms of the
% GNU General Public License as published by the Free Software
% Foundation, either version 3 of the License, or (at your option)
% any later version.
%
% This document is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this document. If not, see <http://www.gnu.org/licenses/>.
%
% You should have received a copy of the Creative Commons
% Attribution-ShareAlike 3.0 Unported License along with this
% document. If not, see <http://creativecommons.org/licenses/>.
% README: Versuch 2: Weltraum-Simulation
\documentclass[a4paper]{article}
\usepackage{pgscript}
\usepackage{multicol}
%\usepackage{sfmath}
\sloppy
\raggedcolumns
\pagestyle{empty}
\addtolength{\textheight}{1cm}
\newcommand{\sep}{~$\cdot$~}
\newcommand{\mylicense}{CC BY-SA (Version 4.0) oder GNU GPL (Version 3 oder höher)}
\begin{document}
\makebox(0,0.005)[tl]{\includegraphics[scale=0.72]{logo-hochschule-bochum-cvh-text-v2.pdf}}\hfill
\makebox(0,0)[tr]{\includegraphics[scale=0.5]{logo-hochschule-bochum.pdf}}
\par\bigskip\bigskip
\begin{center}
\Large\textbf{Praktikumsversuch 2: Weltraum-Simulation}
\par\medskip
\normalsize Hardwarenahe Programmierung\sep
Wintersemester 2020/21\sep
Prof.~Dr.~Peter Gerwinski
\end{center}
Aufgabe: Schreiben Sie ein C-Programm,
das die Bahnen von beliebig vielen Massenpunkten unter Einfluß der Gravitation
simuliert und in bewegter Grafik darstellt.
\begin{multicols}{2}
\begin{itemize}
\item
Zwei Massenpunkte ("`Himmelskörper"') mit den Massen $m_i$ und $m_j$
an den Orten $\vec{r}_i$ und $\vec{r}_j$ ziehen einander an.
Diese Kraft heißt Gravitation. Sie hat den Betrag:
\begin{equation}
|\vec{F}_{ij}| = \frac{m_j\cdot m_i\cdot G}{|\vec{r}_j - \vec{r}_i|^2}
\end{equation}
Hierbei ist $G$ eine Konstante (Gravitationskonstante).
\item
Die auf einen Himmelskörper wirkende Gesamtkraft $\vec{F}_i$
ergibt sich als Summe der von allen anderen Himmelskörpern herrührenden
Gravitationskräfte:
\begin{equation}
\vec{F}_i = \sum_{j=0,\,j\ne i}^{N - 1} \vec{F}_{ij}
\end{equation}
\item
Die Gravitationskraft beschleunigt jeden Himmelskörper gemäß:
\begin{equation}
\vec{F_i} = m_i\cdot \vec{a_i}
\end{equation}
\item
Beispiel: Wir betrachten zwei Himmelskörper. Einer davon ("`Zentralgestirn"')
ruht im Zentrum ($\vec{r}_0 = 0$, $\vec{v}_0 = 0$)
und hat eine wesentlich größere Masse als der andere
("`Satellit"', $m_1 \ll m_0$). Mit geeignetem Anfangsort $\vec{r}_1$
und geeigneter Anfangsgeschwindigkeit $\vec{v}_1$ beschreibt dann
der Satellit eine elliptische Umlaufbahn um das Zentralgestirn.
\item
Wir rechnen in zwei Dimensionen $x$ und $y$.
\item
Für die Zerlegung einer Kraft $\vec{F}_{ij}$ in $x$- und $y$-Komponenten
benötigen Sie nur die Grundrechenarten und die Wurzelfunktion,
jedoch insbesondere \emph{keine} trigonometrischen Funktionen:
\begin{equation}
\vec{F}_{ij} = |\vec{F}_{ij}| \cdot \frac{\vec{r}_j - \vec{r}_i}{|\vec{r}_j - \vec{r}_i|}
\end{equation}
\item
Die Wurzelfunktion \lstinline{sqrt()} finden Sie
in der Mathematik-Bibliothek.
Um diese zu nutzen, verwenden Sie \lstinline{#include <math.h>} im Quelltext,
und geben Sie beim \lstinline[style=cmd]{gcc}-Aufruf
\lstinline[style=cmd]{-lm} mit an.
\columnbreak
\item
Für die Simulation betrachten wir das System in kurzen Zeitintervallen $dt$
und berechnen die Änderungen des Ortes $\vec{r}_i = (x_i,y_i)$
und der Geschwindigkeit $\vec{v}_i = (v_{xi},v_{yi})$ jedes Himmelskörpers
mit Hilfe des expliziten Eulerschen Polygonzugverfahrens.
\par
(Wer möchte, darf natürlich auch andere Verfahren anwenden,
beispielsweise das klassische Runge-Kutta-Verfahren 4.~Ordnung.)
\item
Für eine derartige Simulation
einschließlich ihrer Darstellung als bewegte Grafik
können Sie sich von dem Beispiel-Programm \gitfile{hp}{20201217}{gtk-16.c}
inspirieren lassen.
% (Compilieren mit:
% \lstinline[style=cmd]{gcc}
% \lstinline[style=cmd]{-Wall}
% \lstinline[style=cmd]{-O}
% \lstinline[style=cmd]{gtk-16.c}
% \lstinline[style=cmd]{$(pkg-config}
% \lstinline[style=cmd]{--cflags}
% \lstinline[style=cmd]{--libs}
% \lstinline[style=cmd]{gtk+-3.0)}
% \lstinline[style=cmd]{-o}
% \lstinline[style=cmd]{gtk-16})
\item
In einer \file{GTK+}-\lstinline{drawing_area}
liegt der Nullpunkt der Zeichnung oben links,
eine Längeneinheit entspricht einem Pixel,
und die $y$-Koordinate wächst nach unten.
Es empfiehlt sich, die Koordinaten so umzurechnen,
daß der Nullpunkt in der Mitte der Zeichnung liegt,
die Längeneinheit Ihrem persönlichen Geschmack entspricht
und die $y$-Koordinate nach oben wächst.
\item
Beispiel-Szenarien für 3 oder mehr Körper:
\vspace{-\smallskipamount}
\begin{itemize}\itemsep0pt
\item
Planet mit Mond umkreist Sonne
\item
Sonne mit mehreren Planeten, die sich gegenseitig beeinflussen
\item
zwei Sonnen umkreisen sich gegenseitig, Planet kreist drumherum
\item
Raumsonde besucht nacheinander mehrere Planeten
\end{itemize}
\item
\textbf{Hinweis:}
Speichern Sie die verschiedenen Körper nicht als separate Variable,
sondern in einem Array. Ihr Programm wird dadurch nicht nur flexibler,
sondern auch übersichtlicher und weniger fehleranfällig.
\item
\textbf{Abgabe:}
Ihre Quelltexte mit den Lösungen der Praktikumsaufgabe schicken Sie bitte
per E-Mail an \file{peter.gerwinski@hs-bochum.de}
mit dem \textbf{Betreff:} \lstinline[style=terminal]{aezeev1C}
unter Angabe von Name, Matrikel-Nummer,
Studiengang (MI/MP/TI) und Studienmodell (KIA/KIS/GS).
\end{itemize}
\end{multicols}
\vspace*{-\bigskipamount}
\strut\hfill\emph{Viel Erfolg!}\qquad\qquad
\vfill
\begingroup
\small
\setlength{\leftskip}{3cm}
Stand: 17.\ Dezember 2020
% Soweit nicht anders angegeben:\\
Copyright \copyright\ 2014, 2015, 2018, 2019, 2020\quad Peter Gerwinski\\
Lizenz: \mylicense
Sie können diese Praktikumsunterlagen einschließlich \LaTeX-Quelltext
und Beispielprogramm herunterladen unter:
\url{https://gitlab.cvh-server.de/pgerwinski/hp}
\endgroup
\end{document}
File added
% hp-musterloesung-20201217.pdf - Solutions to the Exercises on Low-Level Programming
% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020 Peter Gerwinski
%
% This document is free software: you can redistribute it and/or
% modify it either under the terms of the Creative Commons
% Attribution-ShareAlike 3.0 License, or under the terms of the
% GNU General Public License as published by the Free Software
% Foundation, either version 3 of the License, or (at your option)
% any later version.
%
% This document is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this document. If not, see <http://www.gnu.org/licenses/>.
%
% You should have received a copy of the Creative Commons
% Attribution-ShareAlike 3.0 Unported License along with this
% document. If not, see <http://creativecommons.org/licenses/>.
% README: Kondensator, hüpfender Ball
\documentclass[a4paper]{article}
\usepackage{pgscript}
\usepackage{gnuplot-lua-tikz}
\begin{document}
\section*{Hardwarenahe Programmierung\\
Musterlösung zu den Übungsaufgaben -- 17.\ Dezember 2020}
\exercise{Kondensator}
Ein Kondensator der Kapazität $C = 100\,\mu{\rm F}$
ist auf die Spannung $U_0 = 5\,{\rm V}$ aufgeladen
und wird über einen Widerstand $R = 33\,{\rm k}\Omega$ entladen.
\begin{enumerate}[(a)]
\item
Schreiben Sie ein C-Programm, das
den zeitlichen Spannungsverlauf in einer Tabelle darstellt.
\points{5}
\item
Schreiben Sie ein C-Programm, das ermittelt,
wie lange es dauert, bis die Spannung unter $0.1\,{\rm V}$ gefallen ist.
\points{4}
\item
Vergleichen Sie die berechneten Werte mit der exakten theoretischen Entladekurve:
\begin{math}
U(t) = U_0 \cdot e^{-\frac{t}{RC}}
\end{math}\\
\points{3}
\end{enumerate}
Hinweise:
\begin{itemize}
\item
Für die Simulation zerlegen wir den Entladevorgang in kurze Zeitintervalle $dt$.
Innerhalb jedes Zeitintervalls betrachten wir den Strom $I$ als konstant
und berechnen, wieviel Ladung $Q$ innerhalb des Zeitintervalls
aus dem Kondensator herausfließt.
Aus der neuen Ladung berechnen wir die Spannung am Ende des Zeitintervalls.
\item
Für den Vergleich mit der exakten theoretischen Entladekurve
benötigen Sie die Exponentialfunktion \lstinline{exp()}.
Diese finden Sie in der Mathematik-Bibliothek:
\lstinline{#include <math.h>} im Quelltext,
beim \lstinline[style=cmd]{gcc}-Aufruf \lstinline[style=cmd]{-lm} mit angeben.
\item
$Q = C \cdot U$,\quad $U = R \cdot I$,\quad $I = \frac{dQ}{dt}$
\end{itemize}
\solution
\begin{itemize}
\item
\textbf{Schreiben Sie ein C-Programm, das
den zeitlichen Spannungsverlauf in einer Tabelle darstellt.}
In dem Programm \gitfile{hp}{20201217}{loesung-1a.c}
arbeiten wir, dem ersten Hinweis folgend,
mit einem Zeitintervall von \lstinline{dt = 0.01}.
Mit dieser Schrittweite lassen wir uns eine Tabelle ausgeben,
die jeweils die Zeit und durch die Simulation berechnete Spannung ausgibt.
Wir simulieren, wie die Ladung $Q = C \cdot U$ des Kondensators
im Laufe der Zeit abfließt.
Dazu berechnen wir in jedem Zeitschritt zunächst den Strom $I = U / R$,
der aus dem Kondensator fließt.
Dieser Strom bewirkt, daß innerhalb des Zeitintervalls $dt$
die Ladung $dQ = I \cdot dt$ aus dem Kondensator abfließt.
Am Ende des Zeitintervalls berechnen wir die zur neuen Ladung $Q$
gehörende neue Spannung $U = Q / C$.
Für eine einfache Ausgabe der Tabelle
verwenden wir die Formatspezifikationen \lstinline{%10.3lf} für drei
bzw.\ \lstinline{%15.8lf} für acht Nachkommastellen Genauigkeit.
Damit schreiben wir jeweils eine \emph{lange Fließkommazahl\/} (\lstinline{%lf})
rechtsbündig in ein Feld der Breite 10 bzw.\ 15
und lassen uns 3 bzw.\ 8 Nachkommastellen ausgeben.
Wir compilieren das Programm mit:
\lstinline[style=cmd]{gcc -Wall -O loesung-1a.c -o loesung-1a}
\item
\textbf{Schreiben Sie ein C-Programm, das ermittelt,
wie lange es dauert, bis die Spannung unter \boldmath $0.1\,{\rm V}$ gefallen ist.}
Wir ändern das Programm \gitfile{hp}{20201217}{loesung-1a.c} so ab,
daß zum einen die Schleife abbricht, sobald die Spannung
den Wert $0.1\,{\rm V}$ unterschreitet (\gitfile{hp}{20201217}{loesung-1b.c}),
und daß zum anderen nicht jedesmal eine Zeile für die Tabelle ausgegeben wird,
sondern erst am Ende die Zeit (und die Spannung).
Der Ausgabe entnehmen wir, daß die Spannung bei etwa $t = 12.90\,{\rm s}$
den Wert $0.1\,{\rm V}$ unterschreitet.
\item
\textbf{Vergleichen Sie die berechneten Werte
mit der exakten theoretischen Entladekurve:\\[0.5\smallskipamount]
\boldmath
\begin{math}
U(t) = U_0 \cdot e^{-\frac{t}{RC}}
\end{math}}
Wir ändern das Programm \gitfile{hp}{20201217}{loesung-1a.c} so ab,
daß es zusätzlich zur Zeit und zur simulierten Spannung
die exakte Spannung $U_0 \cdot e^{-\frac{t}{RC}}$
gemäß der theoretischen Entladekurve ausgibt (\gitfile{hp}{20201217}{loesung-1c.c}),
Da dieses Programm die Exponentialfunktion verwendet, müssen wir nun
beim Compilieren zusätzlich \lstinline[style=cmd]{-lm}\hspace{1pt}
für das Einbinden der Mathematik-Bibliothek angeben.
Der erweiterten Tabelle können wir entnehmen,
daß die durch die Simulation berechnete Spannung
mit der Spannung $U_0 \cdot e^{-\frac{t}{RC}}$
gemäß der theoretischen Entladekurve
bis auf wenige Prozent übereinstimmt.
Dies ist für viele praktische Anwendungen ausreichend,
wenn auch nicht für Präzisionsmessungen.
Wenn Sie die Ausgabe des Programms, z.\,B.\ mit
\lstinline[style=cmd]{./loesung-1c > loesung-1c.dat},
in einer Datei \gitfile{hp}{20201217}{loesung-1c.dat} speichern,
können Sie sich die beiden Kurven graphisch darstellen lassen,
z.\,B.\ mit \file{gnuplot} und dem folgenden Befehl:
\begin{lstlisting}[style=cmd,gobble=8]
plot "loesung-1c.dat" using 1:2 with lines title "Simulation",
"loesung-1c.dat" using 1:3 with lines title "Theorie"
\end{lstlisting}
\begin{center}
\input{loesung-1c.tikz}
\end{center}
Der Unterschied zwischen der simulierten und der theoretischen Entladungskurve
ist mit bloßem Auge nicht sichtbar.
\end{itemize}
\vfill
\exercise{Fehlerhaftes Programm: Hüpfender Ball}
Das auf der nächsten Seite abgedruckte GTK+-Programm
(Datei: \gitfile{hp}{20201217}{aufgabe-2.c}) soll einen
hüpfenden Ball darstellen, ist jedoch fehlerhaft.
\begin{enumerate}[\quad(a)]
\item
Warum sieht man lediglich ein leeres Fenster?
Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben?
\points{3}
\item
Nach der Fehlerbehebung in Aufgabenteil (a)
zeigt das Programm einen unbeweglichen Ball.
Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben, und warum?
\points{2}
\item
Erklären Sie das merkwürdige Hüpfverhalten des Balls.
Wie kommt es zustande?
Was an diesem Verhalten ist korrekt, und was ist fehlerhaft? \points{5}
\item
Welche Befehle muß man in welcher Weise ändern,
um ein realistischeres Hüpf-Verhalten zu bekommen? \points{2}
\end{enumerate}
Hinweis: Das Hinzuziehen von Beispiel-Programmen aus der Vorlesung
ist ausdrücklich erlaubt -- auch in der Klausur.
Allgemeiner Hinweis:
Wenn Sie die Übungsaufgaben zu dieser Lehrveranstaltung
als PDF-Datei betrachten und darin auf die Dateinamen klicken,
können Sie die Beispiel-Programme direkt herunterladen.
Dadurch vermeiden Sie Übertragungsfehler.
\clearpage
\vbox to \textheight{\vspace*{-0.5cm}\begin{lstlisting}
#include <gtk/gtk.h>
#define WIDTH 320
#define HEIGHT 240
double t = 0.0;
double dt = 0.2;
int r = 5;
double x = 10;
double y = 200;
double vx = 20;
double vy = -60;
double g = 9.81;
gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
{
GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
gdk_cairo_set_source_rgba (c, &blue);
cairo_arc (c, x, y, r, 0, 2 * G_PI);
cairo_fill (c);
return FALSE;
}
gboolean timer (GtkWidget *widget)
{
t += dt;
x += vx * dt;
y += vy * dt;
vx = vx;
vy = 0.5 * g * (t * t);
if (y + r >= HEIGHT)
vy = -vy * 0.9;
if (x + r >= WIDTH)
vx = -vx * 0.9;
if (x - r <= 0)
vx = -vx * 0.9;
gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, widget);
return FALSE;
}
int main (int argc, char **argv)
{
gtk_init (&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_show (window);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
GtkWidget *drawing_area = gtk_drawing_area_new ();
gtk_widget_show (drawing_area);
gtk_container_add (GTK_CONTAINER (window), drawing_area);
gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
gtk_main ();
return 0;
}
\end{lstlisting}\vss}
\solution
\begin{enumerate}[\quad(a)]
\item
\textbf{Warum sieht man lediglich ein leeres Fenster?
Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben?}
Die für das Zeichnen zuständige Callback-Funktion wurde zwar geschrieben,
aber nicht installiert.
Um dies zu beheben, ergänze man den folgenden Befehl im Hauptprogramm:
\lstinline{g_signal_connect (drawing_area, "draw", G_CALLBACK (draw), NULL);}
Dies erkennt man sehr schnell durch Vergleich mit dem Beispiel-Programm
\gitfile{hp}{20201217}{gtk-16.c}.
\item
\textbf{Nach der Fehlerbehebung in Aufgabenteil (a)
zeigt das Programm einen unbeweglichen Ball.
Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben, und warum?}
Die Timer-Callback-Funktion wurde zwar geschrieben, aber nicht installiert.
Um dies zu beheben, ergänze man den folgenden Befehl im Hauptprogramm:
\lstinline{g_timeout_add (50, (GSourceFunc) timer, drawing_area);}
Auch dies erkennt man sehr schnell durch Vergleich mit dem Beispiel-Programm
\gitfile{hp}{20201217}{gtk-16.c}.
\item
\textbf{Erklären Sie das merkwürdige Hüpfverhalten des Balls.
Wie kommt es zustande?
Was an diesem Verhalten ist korrekt, und was ist fehlerhaft?}
Die Geschwindigkeit in $y$-Richtung wächst immer weiter.
Der Grund dafür ist, daß die $y$-Komponente der Geschwindigkeit
nicht auf physikalisch sinnvolle Weise berechnet wird.
In der dafür zuständigen Zeile
\lstinline{vy = 0.5 * g * (t * t);}
wird stattdessen der Weg in $y$-Richtung bei einer gleichmäßig
beschleunigten Bewegung berechnet und als Geschwindigkeit verwendet.
\item
\textbf{Welche Befehle muß man in welcher Weise ändern,
um ein realistischeres Hüpf-Verhalten zu bekommen?}
Da der Ball am Boden abprallen soll, ist es \emph{nicht\/} sinnvoll,
die $y$-Komponente der Geschwindigkeit über die bekannte physikalische
Formel $v_y = -g\cdot t$ für die Geschwindigkeit in einer
gleichmäßig beschleunigten Bewegung zu berechnen.
Stattdessen ist es sinnvoll, die \emph{Geschwindigkeitsänderung\/}
innerhalb des Zeitintervalls \lstinline{dt}
zur Geschwindigkeitskomponente zu addieren:
\lstinline{vy += g * dt;}
Auch dies erkennt man sehr schnell durch Vergleich mit dem Beispiel-Programm
\gitfile{hp}{20201217}{gtk-16.c}.
\end{enumerate}
\end{document}
File added
% hp-uebung-20201217.pdf - Exercises on Low-Level Programming
% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020 Peter Gerwinski
%
% This document is free software: you can redistribute it and/or
% modify it either under the terms of the Creative Commons
% Attribution-ShareAlike 3.0 License, or under the terms of the
% GNU General Public License as published by the Free Software
% Foundation, either version 3 of the License, or (at your option)
% any later version.
%
% This document is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this document. If not, see <http://www.gnu.org/licenses/>.
%
% You should have received a copy of the Creative Commons
% Attribution-ShareAlike 3.0 Unported License along with this
% document. If not, see <http://creativecommons.org/licenses/>.
% README: Kondensator, hüpfender Ball
\documentclass[a4paper]{article}
\usepackage{pgscript}
\begin{document}
% \thispagestyle{empty}
\section*{Hardwarenahe Programmierung\\
Übungsaufgaben -- 17.\ Dezember 2020}
Diese Übung enthält Punkteangaben wie in einer Klausur.
Um zu "`bestehen"', müssen Sie innerhalb von 70 Minuten
unter Verwendung ausschließlich zugelassener Hilfsmittel
12 Punkte (von insgesamt \totalpoints) erreichen.
\exercise{Kondensator}
Ein Kondensator der Kapazität $C = 100\,\mu{\rm F}$
ist auf die Spannung $U_0 = 5\,{\rm V}$ aufgeladen
und wird über einen Widerstand $R = 33\,{\rm k}\Omega$ entladen.
\begin{enumerate}[(a)]
\item
Schreiben Sie ein C-Programm, das
den zeitlichen Spannungsverlauf in einer Tabelle darstellt.
\points{5}
\item
Schreiben Sie ein C-Programm, das ermittelt,
wie lange es dauert, bis die Spannung unter $0.1\,{\rm V}$ gefallen ist.
\points{4}
\item
Vergleichen Sie die berechneten Werte mit der exakten theoretischen Entladekurve:
\begin{math}
U(t) = U_0 \cdot e^{-\frac{t}{RC}}
\end{math}\\
\points{3}
\end{enumerate}
Hinweise:
\begin{itemize}
\item
Für die Simulation zerlegen wir den Entladevorgang in kurze Zeitintervalle $dt$.
Innerhalb jedes Zeitintervalls betrachten wir den Strom $I$ als konstant
und berechnen, wieviel Ladung $Q$ innerhalb des Zeitintervalls
aus dem Kondensator herausfließt.
Aus der neuen Ladung berechnen wir die Spannung am Ende des Zeitintervalls.
\item
Für den Vergleich mit der exakten theoretischen Entladekurve
benötigen Sie die Exponentialfunktion \lstinline{exp()}.
Diese finden Sie in der Mathematik-Bibliothek:
\lstinline{#include <math.h>} im Quelltext,
beim \lstinline[style=cmd]{gcc}-Aufruf \lstinline[style=cmd]{-lm} mit angeben.
\item
$Q = C \cdot U$,\quad $U = R \cdot I$,\quad $I = \frac{dQ}{dt}$
\end{itemize}
\exercise{Fehlerhaftes Programm: Hüpfender Ball}
Das auf der nächsten Seite abgedruckte GTK+-Programm
(Datei: \gitfile{hp}{20201217}{aufgabe-2.c}) soll einen
hüpfenden Ball darstellen, ist jedoch fehlerhaft.
\begin{enumerate}[\quad(a)]
\item
Warum sieht man lediglich ein leeres Fenster?
Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben?
\points{3}
\item
Nach der Fehlerbehebung in Aufgabenteil (a)
zeigt das Programm einen unbeweglichen Ball.
Welchen Befehl muß man ergänzen, um diesen Fehler zu beheben, und warum?
\points{2}
\item
Erklären Sie das merkwürdige Hüpfverhalten des Balls.
Wie kommt es zustande?
Was an diesem Verhalten ist korrekt, und was ist fehlerhaft? \points{5}
\item
Welche Befehle muß man in welcher Weise ändern,
um ein realistischeres Hüpf-Verhalten zu bekommen? \points{2}
\end{enumerate}
Hinweis: Das Hinzuziehen von Beispiel-Programmen aus der Vorlesung
ist ausdrücklich erlaubt -- auch in der Klausur.
Allgemeiner Hinweis:
Wenn Sie die Übungsaufgaben zu dieser Lehrveranstaltung
als PDF-Datei betrachten und darin auf die Dateinamen klicken,
können Sie die Beispiel-Programme direkt herunterladen.
Dadurch vermeiden Sie Übertragungsfehler.
\bigskip
\begin{flushright}
\textit{Viel Erfolg!}
\end{flushright}
\clearpage
\vbox to \textheight{\vspace*{-0.5cm}\begin{lstlisting}
#include <gtk/gtk.h>
#define WIDTH 320
#define HEIGHT 240
double t = 0.0;
double dt = 0.2;
int r = 5;
double x = 10;
double y = 200;
double vx = 20;
double vy = -60;
double g = 9.81;
gboolean draw (GtkWidget *widget, cairo_t *c, gpointer data)
{
GdkRGBA blue = { 0.0, 0.5, 1.0, 1.0 };
gdk_cairo_set_source_rgba (c, &blue);
cairo_arc (c, x, y, r, 0, 2 * G_PI);
cairo_fill (c);
return FALSE;
}
gboolean timer (GtkWidget *widget)
{
t += dt;
x += vx * dt;
y += vy * dt;
vx = vx;
vy = 0.5 * g * (t * t);
if (y + r >= HEIGHT)
vy = -vy * 0.9;
if (x + r >= WIDTH)
vx = -vx * 0.9;
if (x - r <= 0)
vx = -vx * 0.9;
gtk_widget_queue_draw_area (widget, 0, 0, WIDTH, HEIGHT);
g_timeout_add (50, (GSourceFunc) timer, widget);
return FALSE;
}
int main (int argc, char **argv)
{
gtk_init (&argc, &argv);
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_show (window);
gtk_window_set_title (GTK_WINDOW (window), "Hello");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
GtkWidget *drawing_area = gtk_drawing_area_new ();
gtk_widget_show (drawing_area);
gtk_container_add (GTK_CONTAINER (window), drawing_area);
gtk_widget_set_size_request (drawing_area, WIDTH, HEIGHT);
gtk_main ();
return 0;
}
\end{lstlisting}\vss}
\makeatletter
\immediate\write\@mainaux{\string\gdef\string\totalpoints{\arabic{points}}}
\makeatother
\end{document}
#include <stdio.h>
#include <math.h>
int main (void)
{
double C = 0.0001;
double U0 = 5.0;
double U = U0;
double R = 33000.0;
double t = 0.0;
double dt = 0.01;
double Q = C * U;
while (U > 0.09)
{
printf ("%10.3lf%15.8lf\n", t, U);
double I = U / R;
Q -= I * dt;
U = Q / C;
t += dt;
}
return 0;
}
#include <stdio.h>
#include <math.h>
int main (void)
{
double C = 0.0001;
double U0 = 5.0;
double U = U0;
double R = 33000.0;
double t = 0.0;
double dt = 0.01;
double Q = C * U;
while (U >= 0.1)
{
double I = U / R;
Q -= I * dt;
U = Q / C;
t += dt;
}
printf ("%10.3lf%15.8lf\n", t, U);
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment