Forum: Mikrocontroller und Digitale Elektronik STM32 OLED MiniScope


von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallöchen..

Auf Basis eines kleinen STM32 Board mit einem STM32F103C8T6 entwickel 
ich zur Zeit ein kleines MiniScope für mein EuroRack. Wellenform und 
Frequenz werden auf dem kleinen 0.89" OLED Display bereits angezeig. Was 
noch fehlt ist ein kleiner Spektrumanalyse. Mal schaun wie ich das 
programmieren kann.

Den Code gibts später..

Youtube: https://www.youtube.com/watch?v=3xvXjU5WA7M

von Hans (Gast)


Lesenswert?

Rolf D. schrieb:
> Den Code gibts später..

Hoffentlich. Ansonsten ist dein Post nämlich nur Angabe.

von Stefan F. (Gast)


Lesenswert?

Rolf D. schrieb:
> Den Code gibts später..

Ja bitte. Das ist ein schönes Projekt zum Nachbasteln.

von Rolf D. (rolfdegen)


Lesenswert?

Schaltplan und Code sind in Arbeit. Vlt wird es auch ein DIY Bausatz mit 
Platine und Frontblende geben. Mal schaun..

Folgende Funktionen sind geplant bzw schon fertig: 1 Kanal Audio-In und 
Out. Menüsteuerung mit Encoder. Welleformdarstellung, Frequenzmessung, 
Spektrumanalyse falls der Prozessor (STM32F103C8T6) dafür schnell genug 
ist, Ausgabe eines Testton für 440Hz Abgleich, Trigger- und 
Pegelanpassung. Die Breite des Moduls wird ca. 31mm betragen und 
Standarthöhe haben.

Meine größtes 
Projekt:http://cczwei-forum.de/cc2/thread.php?threadid=5878&page=34&sid=ebda167b65cda8a49cf9b28a4719d6fa

Gruß Rolf

von Rolf D. (rolfdegen)


Lesenswert?

Hallöchen und guten Morgen..

Wie kann ich während der Laufzeit die Sample Rate im ADC ändern.

Meine das hier: sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;

Beitrag #6001768 wurde von einem Moderator gelöscht.
von Rolf D. (rolfdegen)


Lesenswert?

Hallöchen..

Ich hab für mich eine praktische Lösung gefunden. Ich rufe in der main.c 
für die Änderung der Samplerate eine eigene Initialisierung für den ADC1 
auf in der die SampleRate einfach überschrieben wird. Die eigentliche 
Initialisierung für den ADC1 erfolgt vorher. Nach der erneuten 
Initialisierung in der Tastenabfrage muss der ADC1 wieder neu gestartet 
werden. Ist zwar nicht elegant programmiert aber es funktioniert.

Tastenabfrage in der main.c
1
switch(TBase_sw){
2
             case 0:  TIM3->ARR = 320;      // Scope TimeBase
3
                   MX_ADC1_Init1();      // Sample rate 1.5 cycles
4
                   HAL_ADC_Start (&hadc1);
5
                   ssd1306_SetCursor(0,0);
6
                   ssd1306_WriteString("100us", Font_7x10, White);
7
                   ssd1306_UpdateScreen();
8
                   break;
9
             case 1:  TIM3->ARR = 800;      // Scope TimeBase
10
                         MX_ADC1_Init2();      // Sample rate 7.5 cycles
11
                   HAL_ADC_Start (&hadc1);
12
                   ssd1306_SetCursor(0,0);
13
                   ssd1306_WriteString("250us", Font_7x10, White);
14
                   ssd1306_UpdateScreen();
15
                   break;
16
             case 2:  TIM3->ARR = 1600;      // Scope TimeBase
17
                         MX_ADC1_Init3();      // Sample rate 13.5 cycles
18
                   HAL_ADC_Start (&hadc1);
19
                      ssd1306_SetCursor(0,0);
20
                   ssd1306_WriteString("500us", Font_7x10, White);
21
                   ssd1306_UpdateScreen();
22
                   break;
23
             case 3:   TIM3->ARR = 3200;      // Scope TimeBase
24
                         MX_ADC1_Init4();      // Sample rate 28.5 cycles
25
                         HAL_ADC_Start (&hadc1);
26
                      ssd1306_SetCursor(0,0);
27
                   ssd1306_WriteString("1.0ms", Font_7x10, White);
28
                   ssd1306_UpdateScreen();
29
                   break;
30
             case 4:  TIM3->ARR = 8000;      // Scope TimeBase 3:
31
                         MX_ADC1_Init5();      // Sample rate 41.5 cycles
32
                         HAL_ADC_Start (&hadc1);
33
                         ssd1306_SetCursor(0,0);
34
                   ssd1306_WriteString("2.5ms", Font_7x10, White);
35
                   ssd1306_UpdateScreen();
36
                   break;
37
             case 5:   TIM3->ARR = 16000;      // Scope TimeBase
38
                         MX_ADC1_Init6();      // Sample rate 55.5 cycles
39
                         HAL_ADC_Start (&hadc1);
40
                     ssd1306_SetCursor(0,0);
41
                   ssd1306_WriteString("5.0ms", Font_7x10, White);
42
                   ssd1306_UpdateScreen();
43
                   break;
44
             case 6:  TIM3->ARR = 32000;      // Scope TimeBase
45
                         MX_ADC1_Init7();      // Sample rate 71.5 cycles
46
                         HAL_ADC_Start (&hadc1);
47
                      ssd1306_SetCursor(0,0);
48
                   ssd1306_WriteString("10ms", Font_7x10, White);
49
                   ssd1306_UpdateScreen();
50
                   break;
51
             case 7:  TIM3->ARR = 64000;      // Scope TimeBase
52
                         MX_ADC1_Init8();      // Sample rate 239.5 cycles
53
                   HAL_ADC_Start (&hadc1);
54
                   ssd1306_SetCursor(0,0);
55
                   ssd1306_WriteString("20ms", Font_7x10, White);
56
                   ssd1306_UpdateScreen();
57
                   break;
58
}

Initialisierung in adc.c
1
/* ADC1 init function */
2
void MX_ADC1_Init(void)
3
{
4
  ADC_ChannelConfTypeDef sConfig = {0};
5
6
  /** Common config 
7
  */
8
  hadc1.Instance = ADC1;
9
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
10
  hadc1.Init.ContinuousConvMode = ENABLE;
11
  hadc1.Init.DiscontinuousConvMode = DISABLE;
12
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
13
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
14
  hadc1.Init.NbrOfConversion = 1;
15
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
16
  {
17
    Error_Handler();
18
  }
19
  /** Configure Regular Channel 
20
  */
21
  sConfig.Channel = ADC_CHANNEL_1;
22
  sConfig.Rank = ADC_REGULAR_RANK_1;
23
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
24
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
25
  {
26
    Error_Handler();
27
  }
28
29
}
30
31
void MX_ADC1_Init1(void)
32
{
33
  ADC_ChannelConfTypeDef sConfig = {0};
34
35
  sConfig.Channel = ADC_CHANNEL_1;
36
  sConfig.Rank = ADC_REGULAR_RANK_1;
37
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
38
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
39
    {
40
      Error_Handler();
41
    }
42
}
43
44
void MX_ADC1_Init2(void)
45
{
46
  ADC_ChannelConfTypeDef sConfig = {0};
47
48
  sConfig.Channel = ADC_CHANNEL_1;
49
  sConfig.Rank = ADC_REGULAR_RANK_1;
50
  sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5;
51
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
52
    {
53
      Error_Handler();
54
    }
55
}
56
57
58
void MX_ADC1_Init3(void)
59
{
60
  ADC_ChannelConfTypeDef sConfig = {0};
61
62
  sConfig.Channel = ADC_CHANNEL_1;
63
  sConfig.Rank = ADC_REGULAR_RANK_1;
64
  sConfig.SamplingTime = ADC_SAMPLETIME_13CYCLES_5;
65
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
66
    {
67
      Error_Handler();
68
    }
69
}
70
71
void MX_ADC1_Init4(void)
72
{
73
  ADC_ChannelConfTypeDef sConfig = {0};
74
75
  sConfig.Channel = ADC_CHANNEL_1;
76
  sConfig.Rank = ADC_REGULAR_RANK_1;
77
  sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5;
78
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
79
    {
80
      Error_Handler();
81
    }
82
}
83
84
void MX_ADC1_Init5(void)
85
{
86
  ADC_ChannelConfTypeDef sConfig = {0};
87
88
  sConfig.Channel = ADC_CHANNEL_1;
89
  sConfig.Rank = ADC_REGULAR_RANK_1;
90
  sConfig.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;
91
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
92
    {
93
      Error_Handler();
94
    }
95
}
96
97
void MX_ADC1_Init6(void)
98
{
99
  ADC_ChannelConfTypeDef sConfig = {0};
100
101
  sConfig.Channel = ADC_CHANNEL_1;
102
  sConfig.Rank = ADC_REGULAR_RANK_1;
103
  sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES_5;
104
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
105
    {
106
      Error_Handler();
107
    }
108
}
109
110
void MX_ADC1_Init7(void)
111
{
112
  ADC_ChannelConfTypeDef sConfig = {0};
113
114
  sConfig.Channel = ADC_CHANNEL_1;
115
  sConfig.Rank = ADC_REGULAR_RANK_1;
116
  sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
117
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
118
    {
119
      Error_Handler();
120
    }
121
}
122
void MX_ADC1_Init8(void)
123
{
124
  ADC_ChannelConfTypeDef sConfig = {0};
125
126
  sConfig.Channel = ADC_CHANNEL_1;
127
  sConfig.Rank = ADC_REGULAR_RANK_1;
128
  sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
129
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
130
    {
131
      Error_Handler();
132
    }
133
}

Gruß Rolf

: Bearbeitet durch User
von Michael B. (laberkopp)


Lesenswert?

Rolf D. schrieb:
> Den Code gibts später..

Funktioniert bei deinem blue pill clone,
auch wenn du parallel zum 10k R10 noch 1k8 lötest,
der USB Anschluss über generic_boot20_pc13.bin ?

So daß der STM32 über den maple driver anprechbar wird ?
https://circuitdigest.com/microcontroller-projects/programming-stm32f103c8-board-using-usb-port

Bei mir gibt es nach dem flashen des generic_boot20_pc13.bin
nicht mal ein USB 'erkannt' Systemsound, geschweige denn ein
Maple COM Port.

Und bekommst du die möglichen 2.3Msps (7.5Msps
interleaved) mit dem ADC über dein HAL hin ?

von Rolf D. (rolfdegen)


Lesenswert?

Ich programmiere mein STM32F103C8T6 Board über einen STLINK V2 Adapter 
vom Nucleo-Board. USB hab ich noch nicht ausprobiert.

Zum ADC: Laut Datenblatt schaft der STM32F103C8 1MHz Samplerate (12Bit) 
bei 14MHz Clock Frequenz.

von Rolf D. (rolfdegen)


Lesenswert?

Hallöchen..

Kleine Katastrophe! CubeMX hat in der main.c meinen ganzen User Code 
gelöscht. Habe leider das Häckchen bei "Keep User Code when 
re-generating" im Code generator rausgenommen und neuen Code generiert. 
Die alte mein.o ist noch vorhanden. Kann man da was machen ?!

von Johannes S. (Gast)


Lesenswert?

Schonmal versucht aus einem Burger wieder eine Kuh zu machen? Das wird 
leider nix wenn der Editor da kein Backup gespeichert hat.

von NichtWichtig (Gast)


Lesenswert?

Mein Beileid!

Dafür/dagegen gibt es svn & co ;)

Wenn man aufpaßt klappt das mit CubeMX und nachträglich rumfummeln 
erstaunlich gut, ich bin begeistert.
Ersetzt aber kein Repository!

Bzgl. BluePill und USB kann ich sagen das mein LinuxPC den auch mit 10K 
erkennt und als /dev/ttyACM0 einrichtet, Senden/Empfangen klappt.

von OMG (Gast)


Lesenswert?

Rolf D. schrieb:
> Kleine Katastrophe! CubeMX hat in der main.c meinen ganzen User Code
> gelöscht.

NichtWichtig schrieb:
> Mein Beileid!

Meines auch.

Denn Backups sind nur etwas für höchstprivilegierte Leute
mit entsprechend viel Geld in der Portokasse.

Wir armen Schlucker dagegen müssen das Zeugs immer neu eintippen.

von Rolf D. (rolfdegen)


Lesenswert?

Mmm. Schade.. kann man nix machen. Gut das ich Teile vom Quellcode im 
Forum und in anderen Projekten stehen habe. Dann werde ich mir das 
wieder mühselig zusammensetzen.

Frage: Warum werden die User Codes in anderen C-Files wzB adc.c immer 
wieder gelöscht, obwohl ich das Häckchen bei "Keep User Code when
re-generating" gesetzt habe und den Code unter /* USER CODE BEGIN 1 */ 
stehen habe  ?

: Bearbeitet durch User
von Harry L. (mysth)


Lesenswert?

1. ist "Keep User Code when re-generating" die default-Einstellung, und 
wenn du da den Haken ohne Not heraus nimmst, bist du selber Schuld.

2. hat mir CubeMX noch nie den Code versemmelt - das funktioniert genau 
wie es soll, so lange man eigenen Code in die entsprechend markierten 
Bereiche schreibt und die bereichs-Markierungen nicht beschädigt.

3. erkennst du jetzt hoffentlich, daß es sinnvoll ist, eigenen Code auch 
in eigene c-Files zu schreiben.

4.: daß man ab und an auch mal ein Backup anfertigen sollte wurde 
bereits gesagt.

von Rolf D. (rolfdegen)


Lesenswert?

Ich verstehs trotzdem nicht. Haken ist drin und mein Code stand im User 
Bereich. Nachdem ich jetzt wieder in CubeMX Code generiert habe ist 
wieder alles weg. Ist doch Mist :(

von Stefan F. (Gast)


Lesenswert?

Vor lauter "Angst" mache ich das so:

Zwischen die Marker in main.c setze ich ein include Statement das auf 
meine eigene Datei verweist. Dann verliere ich schlimmstensfalls nur 
diese eine Zeile.

Subversion kann ich nur empfehlen. Für Einzelkämpfer ist dieses Tool 
einfacher anzuwenden, als alle anderen Source repositories. Man muss 
nicht einmal einen Subersion-Server installieren.

Dazu empfehle ich das TortoiseSVN Paket, es enthält meiner Meinung nach 
die beste GUI für SVN.

Was macht ein Source Repository?: Es speichert ein Backup deiner 
Quelltexte ab, sobald du das Kommando dazu absetzt. Bei Änderungen 
speichert es nur die Teile ab, die verändert wurden (commit). Deswegen 
kannst du das so oft nutzen, wie du willst - Speicherplatz wird kein 
Problem sein.

Du kannst funktionsfähige Versionen kennzeichnen und mehrere Varianten 
(branches) deines Programms anlegen, um unterschiedliche Versionen 
parallel weiter zu pflegen. Wenn du dann in der aktuellen Version einen 
Fehler korrigierst, kannst du diese Änderung (mit etwas Glück 
vollautomatisch) in die älteren Programmversionen übertragen.

Du kannst jeder Zeit auf ältere Versionen deines Quelltextes zugreifen.

Die Hauptaufgabe dieses Tools ist allerdings, die Änderungen mehrerer 
Entwickler zusammen zu führen (merge). Den Teil wirst du alleine wohl 
selten nutzen.

von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallo..

Die grundsätzliche Schaltung für das meSCOPE ist jetzt fertig. Muss das 
ganze jetzt auf eine Platine löten (siehe Bild).

Schaltplan:
Das Scope hat einen 16Bit DA-Wandler mit zwei Ausgangskanälen. Den hab 
ich für die Schaltungsentwicklung auf eine SOP-8 Platine gelötet. 
Ausgang A ist für die Ausgabe einer Gleichspannung. Ausgang B gibt einen 
440Hz Ton aus.
Beiden DAC-Ausgänge besitzen eine Tristate-Funktion und werden 
abwechselnd geschaltet. Dadurch benötige ich keinen zweiten OP für die 
Ausgabe einer Messspannung.
Über Poti R8 kann die Eingangsspannung für das Scope geregelt werden. 
IC4a begrenzt die Eingangsspannung am AD-Wandler. IC4b ist als 
Komperator geschaltet und für das Triggern der Wellenform zuständig.
Die Stromversorgung (+3.3V) für das STM32 Prozessor-Board liefert die 
+12V Spannung über K1. Hab noch einen Butterwoth-Filter 2.Ordnung für 
den DA-Wandler integriert. Die berechnete Filterfrequenz liegt bei 
10KHz.
Das STM32 Board entspricht von den Abmessungen der Anschlusspins genau 
einer 40pol IC-Fassung.

Gruß Rolf

von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallo zusammen..

Im Schaltplan gibts noch ein paar kleine Änderungen. Die Stromversorgung 
für das Scope kann über Jumper K2 auf +5V oder +12V festgelegt werden. 
An den Steuerleitungen SCL und SDA für das Display fehlten noch die 4.7K 
Pullup- Widerstände.

Alle Bauteile sind jetzt bestückt. Auf der Rückseite befindet sich das 
STM32 BluePill Prozessor Board.

Nächste Schritte sind das Verlöten der restlichen Bauteile und die 
Zusammenführung der einzelnen Software Module im Programm.

Gruß Rolf

von Crazy Harry (crazy_h)


Lesenswert?

Find ich klasse :-) ich lese mit

btw kennst du das: 
http://www.gabotronics.com/development-boards/xmega-xprotolab.htm ?

von Rolf D. (rolfdegen)


Lesenswert?

Danke für den Link. Interessantes Projekt :)

von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallöchen..

Hab mal ein wenig mit dem neuen Frontplatten Designer von Schaefer AG 
gearbeitet. Hier die Frontplatte für den Prototyp. Ich denke, das ich 
noch eine Scala für das Poti einfügen werde. Die aktuellen Kosten für 
eine Frontplatte (Bild) betragen ca. 30 Euro (Schaefer AG). Die 
Abmessungen für die Frontplatte betragen 40x128,4mm und 2mm dick.

Gruß Rolf

: Bearbeitet durch User
von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallöchen..

Die Frontplatte des Scops ist jetzt fertig designed. Etwas 
Schwierigkeiten hatte ich mit dem Frontplatten Designer von Schaefer AG 
und der Grafik für die Poti Scala. Die Scala habe ich mit dem 
FrontDesigner3.0 erzeugt und dann in Gimp als PNG-File exportiert. 
Danach konnte ich die Scala im Frontplatten Designer importieren.

Gruß Rolf

: Bearbeitet durch User
von Rolf D. (rolfdegen)


Angehängte Dateien:

Lesenswert?

Hallöchen..

Mittlerweile habe ich meine Frontplatte von der Firma Schaefer AG 
erhalten. Leider ist der Text über den Reglern etwas zu klein geraten 
und die Bohrlöcher für die Audiobuchsen sind nicht an der richtigen 
Position. Also habe ich jetzt die Dinge korrigiert und die Frontplatte 
nochmal einmal bestellt, mit der Hoffnung das es dieses mal stimmt.


Hab mal aus Lust und Frust ein "Synthmännchen" Logo für meine 
zukünftigen Eurorack Module entwickelt (siehe Bild 2)

von Stefan F. (Gast)


Lesenswert?

Das sieht lustig aus, so ein mini Display in den großen Gehäuse. Den 
Rest würde mit ganz vielen funktionslosen Schaltern und geheimnisvollen 
Beschriftungen voll machen, dann sieht es noch witziger aus.

von Rolf D. (rolfdegen)


Lesenswert?

Hi Stefan

Ja.. Ist eine coole Idee. Überleg ich mir mal :))

von Johannes S. (Gast)


Lesenswert?

ja, du must noch jung sein und sehr gute Augen haben :)
Ich hätte das eher in ein Handgehäuse mit einer Prüfspitze vorne 
eingebaut.

von Rolf M. (rmagnus)


Lesenswert?

Harry L. schrieb:
> 4.: daß man ab und an auch mal ein Backup anfertigen sollte wurde
> bereits gesagt.

Und dass man seinen Code in einem Versionierungstool (typischerweise 
heute svn oder git) verwaltet! Das ist für mich Grundvoraussetzung bei 
der Software-Entwicklung. Würd ich nie mehr ohne machen.
Das Backup wird dann vom Repository gemacht.

Stefan F. schrieb:
> Subversion kann ich nur empfehlen. Für Einzelkämpfer ist dieses Tool
> einfacher anzuwenden, als alle anderen Source repositories. Man muss
> nicht einmal einen Subersion-Server installieren.

Bei git gibt es nicht mal den Server im klassischen Sinn. Per Default 
ist das Repository erstmal lokal. Allerdings ist git tatsächlich 
deutlich komplizierter in der Anwendung als svn, wobei der Hauptteil der 
Komplexität erst zum Tragen kommt, wenn man mit mehreren Entwicklern 
verteilt arbeitet. Es ist allerdings mit git einfacher als mit svn, wenn 
man mehrere Rechner hat und die Repos dort immer miteinander 
synchronisieren will.

von Rolf D. (rolfdegen)


Lesenswert?

Beim Logo Designe hat mich das hier inspiriert:

https://www.youtube.com/watch?v=J73VdiesIW0

Geiles Video und es passt zur kommenden Weihnachtszeit :)

von Hört sich gut an (Gast)


Lesenswert?

>Bei git gibt es nicht mal den Server im klassischen Sinn. Per Default
>ist das Repository erstmal lokal. Allerdings ist git tatsächlich
>deutlich komplizierter in der Anwendung

Ja da gilt wie so oft, übung macht den Meister. Aber wenn man man dann 
aus dem ff ein git init, git add . und git commit "init repo" macht und 
jedes Projekt in 5 sekunden in eine Versionsverwaltung überführt ist 
schon toll. dann macht das spaß. git push und git fetch brauchst du ja 
nur beim hochladen (wie du ja auch erwähnt hast). Unbedingt vorher mal 
ausprobieren, wie man einen Stand aus einem Commit wieder herstellt 
(gibt es ein paar Fallen). git rocks!

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Normalerweise sollte ein Programm, welches am Code rumfummelt, vorher 
ein backup selbiger Datei machen. Kenne ich eig. nur so, selbst WinMerge 
macht das. Immer. CubeMX nicht?!

von Hört sich gut an (Gast)


Lesenswert?

>Normalerweise sollte ein Programm, welches am Code rumfummelt, vorher
>ein backup selbiger Datei machen. Kenne ich eig. nur so, selbst WinMerge
>macht das. Immer. CubeMX nicht?!

Nö, auch bei git muss man tatsächlich wissen, was man tut. solange es 
nur ums "hinzufügen" von Code geht, bleibt das recht einfach und save. 
Allerdings kann beim Herstellen einiges Schiefgehen. Deswegen sollte man 
den Fall durchspielen, wenn gerade nicht die Hütte brennt

von Stefan F. (Gast)


Lesenswert?

Random .. schrieb:
> vorher ein backup selbiger Datei machen

Wobei das Repsository drei Vorteile bietet:

1) Nachvollziehbarkeit sämtlicher Änderungen von Anfang bis Ende
2) Änderungen mehrerer Benutzer zusammen führen
3) Einzelne Änderungen (nicht komplette Dateien) rückgängig machen

Für einen Einzelkämpfer ist Punkt 2 natürlich irrelevant.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.