Schrittmotor mit Loopdriver ansteuern

Hallo zusammen! :slight_smile:

Für meine Facharbeit muss ich einen Motor mit dem o. g. Looper programmieren. Ziel ist es damit einen Extruder zu betreiben und während des Betriebs die Drehzahl mit einem Poti einzustellen.

Zu erst der hardwareseitige Aufbau:

Wie im Anhang zu sehen betreibe ich den Motor über den Loopdriver. Als Netzteil dient mir ein 24 V Siemens Logo-Netzteil. Die Steuerleitungen werden mit einem Uno verbunden.
Des Weiteren heabe ich noch einen 10k-Poti mit dem ich in den Analogeingang A0 gehe, um die Drehzahl zu verstellen. Eine LCD-Anzeige dient der Ausgabe der aktuellen Drehzahl/Sek.
Die maximale Drehzahl soll 5 Umdrehungen/Sek. sein und minimale 0,0... (Da muss ich nochmal schauen, was sinvoll ist).

Zum Code selbst:
Ich habe erstmal einen einfachen Code geschrieben, um zu testen, ob die Drehzahl auch richtig umgewandelt wird. Dabei gebe ich die Drehzahl als Gleitkommazahl ein und der Uno rechnen daraus die nötige Pulsdauer aus.
Das Funktioniert auch soweit. Anbei der einfache Code:

const int STEP_PIN = 9;
const int Enable_PIN = 13;
const int DIR_PIN = 8;
float val = 0.5;  //Gewünschte Drehzahl/Sekunde
int d = 0;      //Pulszahl/Umdrehung


void setup()
{
  pinMode(STEP_PIN, OUTPUT);
  pinMode(Enable_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  digitalWrite(STEP_PIN, LOW);
  digitalWrite(Enable_PIN, LOW); 
  digitalWrite(DIR_PIN, HIGH);
} 

void loop()
{
  d = 999997/(val*6400);
  //Serial.println(d);
  digitalWrite(STEP_PIN, HIGH);
  delayMicroseconds(3);
  digitalWrite(STEP_PIN, LOW);
  delayMicroseconds(d);
}

Was mir dabei aufgefallen ist, dass die Drehzahl sehr langsam wird, sobald ich mit der Zeile "Serial.println(d);" die Pulszahl versuche auszugeben. Ist das normal, wie sind da eure Erfahrungen?

als nächstes habe ich versucht die Drehzahl über einen Poti zu steuern und dabei die Drehzahl über LCD auszugeben.

Mein erstes Problem, ich kann ihm nicht beibringen, dass er die Potiwerte in eine Gleitkommazahl ausgibt bzw. in eine solche umwandelt.
Das nächste Problem, obwohl er anscheinend den ganzzahligen Werte des Potis richtig mit der map-Funktion umwandelt, stimmt die Drehzahl nicht. Der Motor dreht beim Drehen am Poti unregelmäßig (Die Drehzahl wird mal langsamer, mal schneller).

Anbei der Code:

#include <LiquidCrystal.h>
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

const int STEP_PIN = 9;
const int Enable_PIN = 13;
const int DIR_PIN = 8;
const int potiPin = A0;
int potiWert = 0;
float pwm = 0;
int d = 0;


void setup()
{
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Drehzahl/Sek.:");
  pinMode(STEP_PIN, OUTPUT);
  pinMode(Enable_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  digitalWrite(STEP_PIN, LOW);
  digitalWrite(Enable_PIN, LOW); 
  digitalWrite(DIR_PIN, HIGH);  
} 

void loop()
{
  lcd.setCursor(0, 1);
  lcd.print(pwm);
  potiWert = analogRead(potiPin);
  pwm = map(potiWert, 0, 1023, 0, 5);
  d = 999997/(pwm * 6400);
  
  digitalWrite(STEP_PIN, HIGH);
  delayMicroseconds(3);
  digitalWrite(STEP_PIN, LOW);
  delayMicroseconds(d);
}

Eine letzte grundsätzliche Frage, gibt es eine Möglichkeit die Impulse für den Motor nicht über delay-Funktion auszugeben, da ja dabei der Skript jedesmal angehalten wird.

Ich hoffe ihr könnt mir dabei Helfen, da ich langsam am verzweifeln bin. :confused:

Vielen Dank im Voraus und viele Grüße

Alex

Was mir dabei aufgefallen ist, dass die Drehzahl sehr langsam wird, sobald ich mit der Zeile "Serial.println(d);" die Pulszahl versuche auszugeben. Ist das normal, wie sind da eure Erfahrungen?

Die Ausgabe benötigt Zeit.
Ins besondere, wenn der Buffer des Serial voll ist, dann blockiert Serial.print, bis es seine Zeichen in den Buffer geschrieben hat.

mit dem o. g. Looper

Schön, dass du weißt, was ein Looper ist.
Ich nicht.

Eine letzte grundsätzliche Frage, gibt es eine Möglichkeit die Impulse für den Motor nicht über delay-Funktion auszugeben, da ja dabei der Skript jedesmal angehalten wird.

Ganz sicher JA!
Denn dafür hat Atmel damals die Timer und Interrupts in die AVRs eingebaut.
Ich garantiere dafür, dass in deinem geheimen µC auch ein solches Konzept realisiert ist.

Man kann hier auch Bilder zeigen, unsere werten Tablet-Nutzer sind da ganz wild drauf:

02alex12:
Ich hoffe ihr könnt mir dabei Helfen, da ich langsam am verzweifeln bin. :confused:

Jetzt schon?

02alex12:
const int Enable_PIN = 13;

Nimm einen anderen Pin, da dieser beim Upload blinkt.

02alex12:
Eine letzte grundsätzliche Frage, gibt es eine Möglichkeit die Impulse für den Motor nicht über delay-Funktion auszugeben, da ja dabei der Skript jedesmal angehalten wird.

Siehe #1 oder Du verwendest eine Bibliothek wie AccelStepper.

Hi

Nebenfrage: Wie sinnvoll ist Es, eine Extruder-Schnecke per Stepper anzusteuern?
Beim 3D-Drucker will mir die Sache ja noch einleuchten, bei einem 'ausgewachsenem Gerät' halte ich Das für unnötig kompliziert, Da wäre Was in der Richtung Konstant-Druck ect.pp. irgendwie sinniger - und die Ansteuerung eines DC-Motor ist nicht nur kein Hexenwerk, Es vereinfacht die Sache ungemein, gerade, wenn die Welle doch Mal schneller als 1°/s verdreht werden soll.
(Oder, entgegen meiner Vorstellung, fördert der Extruder auch bei minimalen Zustellungen proportional?)

Beim Stepper: Wie schnell müssen die Schritte später kommen können?
loop()-Durchlaufzeiten von 1ms sollten hinzubekommen sein, womit 1000 Schritte/Sekunde ebenfalls möglich sein sollten.
Ob der nächste Schritt nun dran ist, oder nicht, verrät Euch gleich das Licht - äh, der micros()-Timer.

MfG

Guten morgen allerseits!

Vielen Dank für die schnellen, zahlreichen Antworten! 8)

combie:
Die Ausgabe benötigt Zeit.
Ins besondere, wenn der Buffer des Serial voll ist, dann blockiert Serial.print, bis es seine Zeichen in den Buffer geschrieben hat.

Hm... das ist ja nun doof aber da kann man wahrscheinlich nichts machen.

combie:
Ganz sicher JA!
Denn dafür hat Atmel damals die Timer und Interrupts in die AVRs eingebaut.
Ich garantiere dafür, dass in deinem geheimen µC auch ein solches Konzept realisiert ist.

Vielen Dank für den Tipp, das wird die Rätselslösung sein. :open_mouth:
In diesem Zusammenhang habe ich mich nochmal im Forum umgesehen und diesen Beitrag gefunden. Nach ein paar kleinen Anpassungen läuft der Motor so wie ich mir das gedachte habe. Das Problem dabei ist, dass er beim maximalen Anschlag des Potis zu langsam dreht. Die Vorgabe seitens des Projekts wäre ein Drehzahlbereich von 0 bis 5 min-1.

postmaster-ino:
Nebenfrage: Wie sinnvoll ist Es, eine Extruder-Schnecke per Stepper anzusteuern?
Beim 3D-Drucker will mir die Sache ja noch einleuchten, bei einem 'ausgewachsenem Gerät' halte ich Das für unnötig kompliziert, Da wäre Was in der Richtung Konstant-Druck ect.pp. irgendwie sinniger - und die Ansteuerung eines DC-Motor ist nicht nur kein Hexenwerk, Es vereinfacht die Sache ungemein, gerade, wenn die Welle doch Mal schneller als 1°/s verdreht werden soll.
(Oder, entgegen meiner Vorstellung, fördert der Extruder auch bei minimalen Zustellungen proportional?)

Wie sinnvoll das ist, kann ich dir leider auch nicht beantworten und da gebe ich dir vollkommen recht, ein DC-Motor wäre viel einfacher. Als ich in das Projekt involviert wurde war der Hardwareseitige Aufbau schon fertig.

Das habe ich noch nicht erwäht aber der Extruder soll auf einem großen 3D-Drucker verbaut werden und dort seinen Dienst verrichsten (Stichwort 3D-Druck im Hausbau).

postmaster-ino:
Beim Stepper: Wie schnell müssen die Schritte später kommen können?

Was meinst du damit? Die Drehzahl?

Viele Grüße
Alex

Hi

Ok, bei einem 3D-Drucker ist der Stepper durchaus sinnvoll - in der Industrie hätte ich die Extruder sonst nur kontinuierlich fördern sehen und Das wäre mit DC einfacher hinzubekommen.

Der Stepper braucht ja schrittweise Ansteuerung.
Ke nachdem, was der Arduino sonst noch zu tun hat, wird die loop() so schnell durchlaufen, daß Es reichen kann, einfach in der loop() auf den nächsten Schritt zu warten (Stichwort State-Maschine)..
Dein Stepper braucht 200 Schritte für eine Umdrehung?
Macht 1000/Sekunde für 5 Umdrehungen pro Sekunde - 1 ms loop()-Durchlaufzeit könnte schaffbar sein.
Alternativ eine Stepper-Lib, Die NICHT blockiert, DIe wird dann auch wieder mit Timern laufen.

MfG

postmaster-ino:
... 1 ms loop()-Durchlaufzeit könnte schaffbar sein. ...

1 ms loop()-Durchlaufzeit (1 kHz) halte ich für eine halbe Ewigkeit. IMO sollten problemlos >10 kHz möglich sein.

Gruß

Gregor

Hi

Klar - hier und Da mit ein Wenig LCD, dann wird's schon wieder knapper - wollte eigentlich erst Mal nur eine grobe Zahl wissen, ob wir ohne Innereien hin kommen KÖNNEN.
Wenn's nur der Stepper ist und das Einlesen eines analogen Spannungswert, sollte Sich Da schon Einiges machen lassen.

MfG

Guten Morgen! :slight_smile:

postmaster-ino:
Klar - hier und Da mit ein Wenig LCD, dann wird's schon wieder knapper - wollte eigentlich erst Mal nur eine grobe Zahl wissen, ob wir ohne Innereien hin kommen KÖNNEN.
Wenn's nur der Stepper ist und das Einlesen eines analogen Spannungswert, sollte Sich Da schon Einiges machen lassen.

Da es sich hier um ein Forschungsprojekt handelt würde ich genau aus diesem Grund den Code so gestalten, dass die Steuerung des Motors wenig beeinflüsst wird, wenn es irgendwelche Zusatzfunktionen geben sollte.

Hi

Da Du hier fragst, scheint Dein Wissenstand in Richtung Arduino, 'erweiterbar' zu sein.
Warum antwortest Du nicht auf die Dir gestellten Fragen?
Ganz so wichtig kann die Forschung dann ja doch nicht sein.

Ok, auch wenn Du nicht willst - der 3D-Drucker wird wohl kaum '1 Umdrehung pro Sekunde' an Filament brauchen - damit wären wir DICKE im Bereich, daß man den ganzen Kram in loop() alleine lösen kann.
Auch MIT Zusatzfunktionen, wie ein schickes Blinke-Lämpchen als Warnung, daß Da irgendwas heiß ist ...

Soll gar kein Filament, sondern eher Schnellzement (dann wieder mit Schnecke ...) gefördert werden?
Ist die Düse vll. doch 'etwas' größer, als man sich einen handelsüblichen 3D-Drucker so vorstellt?
Klar, auf dem Weg zum Patent sollten Das Geheimnisse bleiben, wenn man in einem Forum Gratis-Hilfe haben möchte, sollte man aber schon ein/zwei Informationen preis geben - oder, der Geheimhaltung wegen, Geld in die Hand nehmen.

Nun denn, lasset die Forschung beginnen

postmaster-ino:
Hi

Da Du hier fragst, scheint Dein Wissenstand in Richtung Arduino, 'erweiterbar' zu sein.
Warum antwortest Du nicht auf die Dir gestellten Fragen?
Ganz so wichtig kann die Forschung dann ja doch nicht sein.

Ok, auch wenn Du nicht willst - der 3D-Drucker wird wohl kaum '1 Umdrehung pro Sekunde' an Filament brauchen - damit wären wir DICKE im Bereich, daß man den ganzen Kram in loop() alleine lösen kann.
Auch MIT Zusatzfunktionen, wie ein schickes Blinke-Lämpchen als Warnung, daß Da irgendwas heiß ist ...

Soll gar kein Filament, sondern eher Schnellzement (dann wieder mit Schnecke ...) gefördert werden?
Ist die Düse vll. doch 'etwas' größer, als man sich einen handelsüblichen 3D-Drucker so vorstellt?
Klar, auf dem Weg zum Patent sollten Das Geheimnisse bleiben, wenn man in einem Forum Gratis-Hilfe haben möchte, sollte man aber schon ein/zwei Informationen preis geben - oder, der Geheimhaltung wegen, Geld in die Hand nehmen.

Nun denn, lasset die Forschung beginnen

Der Drucker hat eine Größe eines Pkws, die Düse je nach Formaufsatz mehrere Quardratzentimeter, die Extruderschnecke hat einen Durchmesser von 50 mm. Das ganze soll im Bereich Hausbau Anwendung finden.
Ich für meinen Teil soll nur einen Extruder entwickeln, der parallel zum Zement-Druckkopf läuft und die Wandverschalung druckt.

Was ich komklett vergessen habe zu erwähnen, dass der Treiber auf 6400 Mikroschritten eingestellt ist, um eine gleichmäßige Förderung des Materials zu gewähren. Bei 200 Schritten hat der Motor zwischen den Schritten doch zu stark geruckelt.

Hier noch ein Link, wie das Ganze im Serienzustand aussehen soll:
https://tu-dresden.de/feeds/baublog/e1e42a3c045f9ef4e7ce2ba30ad6279d

Ich hoffe, ich konnte jetzt etwas klarheit schaffen.

Anbei noch die Frage, hat sich einer den oben verlinkten Thread angeschaut? Ich denke, dass dort gepostete Code die Rätselslösung sein kann, aber ich bringe den Motor einfach nicht dazu schneller zu drehen.

SaschaW:
Ich beschäftige mich damit, einen Schrittmotortreiber mittels Timer1 mit einem Taktsignal zu versorgen.
Soweit funktioniert das auch.
Nur läuft der Motor recht unruhig.
Jetzt habe ich mir mal ein Oszilloskop geliehen und konnte feststellen, das neben dem Rechteckimpuls auch noch einzelne Spikes ausgegeben werden.

edit:
Programm geändert, jetzt ohne Spikes

/* //////////////////////// Hardware, Ein- & Ausgangsbelegung  //////////////////////////////////////////////////////// 

Arduino  OQ PCB                                OQ PCB     Arduino             Verwendung
                     -------  ------           ___________          --------   --------            --------------
                              (RESET)-----PC6 |1        28| PC5----(ADC5,SCL)  Dig19 Ana5
                     Dig0(RX) (RXD)-------PD0 |2  o   i 27| PC4----(ADC4,SCA)  Dig18 Ana4
                     Dig1(TX) (TXD)-------PD1 |3  o   i 26| PC3----(ADC3)      Dig17 Ana3
                     Dig2     (INT0)------PD2 |4  o   i 25| PC2----(ADC2)      Dig16 Ana2
                     Dig3     (INT1)------PD3 |5  o   i 24| PC1----(ADC1)      Dig15 Ana1
                     Dig4     (XCK/TO)----PD4 |6  o   i 23| PC0----(ADC0)      Dig14 Ana0  <======= Sollwertvorgabe
                                          VCC |7  o   o 22| GND
                                          GND |8  o   o 21| AREF
                              (XTAL1)-----PB6 |9  i   o 20| AVCC
                              (XTAL2)-----PB7 |10 i   o 19| PB5----(SCK)       Dig13
                     Dig5,PWM (T1)--------PD5 |11 o   o 18| PB4----(MISO)      Dig12
                     Dig6,PWM (AIN0)------PD6 |12 o   o 17| PB3----(MOSI,OC2)  Dig11,PWM
                     Dig7     (AIN1)------PD7 |13 o   o 16| PB2----(SS,OC1B)   Dig10,PWM
                     Dig8     (ICP1)------PB0 |14 o   o 15| PB1----(OC1A)      Dig 9,PWM   =======> Taktausgang
                                               -----------
*/

int Taktausgang   = 9 ;  // Digitalausgang 9 = Taktausgang, ist Hardwaremäßig vorgegeben
int Analogeingang = A0;  // Analogeingang  0 = Sollwertvorgabe zur  Frequenzerzeugung

/////////////////////////// Takterzeugung  //////////////////////////////////////////

uint16_t taktWert = 0;              // Variable für Zählwert 0 - 65535
uint16_t taktSpeed = 0;             // Variable Schrittweite fürs Zählen

SIGNAL(TIMER1_OVF_vect)             // Interruptroutine, wird bei jedem Timerüberlauf aufgerufen
{                          
taktWert += taktSpeed;             // taktWert um taktSpeed erhöhen
if(taktWert >= 45000)              // Rechteck erzeugen, ist Symmetrisch bei 32768
  digitalWrite(Taktausgang, HIGH);
else
  digitalWrite(Taktausgang, LOW);
}

//////////////////////// Initialisierung  ///////////////////////////////////////////
void setup()
{                  
pinMode(Taktausgang, OUTPUT);        // Taktausgang belegen
Serial.begin(9600);                  // Kommunikation ermöglichen      
                                     // Timer1 konfigurieren / Registerbits setzen    
TCCR1A = (1<<WGM10)| (1<<COM1A1);    // Fast PWM 8 bit | Kanal A rücksetzen wenn gleich
TCCR1B = (1<<CS10) | (1<<WGM12) ;    // Kein Prescaler | Fast PWM 8 bit
TIMSK1 |= (1<<TOIE1);                // Interruptroutine aktivieren
}
//////////////////////// Programm  //////////////////////////////////////////////////
void loop()
{
 taktSpeed = analogRead(Analogeingang);          // Schrittmotordrehzahl
 Serial.println(taktSpeed);  // Sollwertausgabe
}

Gruß
Alex

Ich habe gerade zufällig noch ein Video gefunden, wo der Drucker zu sehen ist (ab 1:15), um die Größenrdnung zu verdeutlichen:

Letztlich soll das Ding wohl kommerziell eingesetzt werden. Insofern finde ich blöd, dafür kostenlose Hilfe in Anspruch zu nehmen.

Andererseits finde ich, dass Ehrlichkeit belohnt werden sollte. Hier tanzen ab und zu auch Leute an, die verschleiern wollen, dass die hiesige Hilfsbereitschaft einfach nur ausgenutzt werden soll.

Wäre es nicht sinnvoll, statt eines Schrittmotors einen DC-Getriebemotor zu wählen? Wenn der einen Drehencoder hat, kann man auch dessen Leistung gut steuern. Zudem benötigt der wesentlich weniger Energie und ist billiger.

Gruß

Gregor

Hi

Danke für diese Informationen und auch für das Video.
Was direkt auffällt: tonnenweise Aufwand in die Konstruktion der Führungen und dann ein wabbelnder Schlauch - da hätten Schubladenauszüge das Budget erfreulich schmäler ausfallen lassen können.
Auch die angedachte Nutzung am Ende des Ausleger einer Betonpumpe lässt mich am Millimeter zweifeln.
Deshalb finde ich 'Bei 200 Schritten hat der Motor zwischen den Schritten doch zu stark geruckelt.' auch Heulen auf sehr hohem Niveau.
Wir reden hier immer noch von Beton (bzw. dann wohl eher Speiß, da mir für Beton 'die Brocken' fehlen, mag aber Definitionssache sein), Der, zumindest in jetzigem Stadium, mit Mühe und Not auf den Zentimeter auf Höhe gebracht wird.

Nun gut - Dein Sketch oben.
Jede serielle Ausgabe braucht Zeit.
Die angegebene Geschwindigkeit durch 10 sind die möglichen Zeichen pro Sekunde.
Bei 9600 Baud wären ca. 1000 Zeichen pro Sekunde möglich.
Ein 'Ok' bräuchte so ca. 4ms.
Ausgaben per SPI auf ein LCD o.Ä. sollten sich Da zeitlich um Längen besser machen, da SPI mit wesentlich höherer Taktrate betrieben werden kann (MHz, statt der 115kHz bei der Seriellen).
Je einfacher Du rechnen kannst, desto schneller wird der Kram.
Wenn die Durchlaufzeit von loop() aber eh nicht mehr reicht, lässt man das Pinwackeln von einem Timer machen und schaut halt in jedem loop()-Durchlauf, ob an der Geschwindigkeit noch was zu verändern ist.
Damit hat man dann zwar wohl mehrere Takte, in Denen man nicht eingreifen kann (der µC ist einfach zu lahm, sagt gerade 'Hallo' oder macht sonstigen Kram), aber da die loop() immer noch in ms-Zeiten bewältigt wird, sollte Das kein Problem darstellen - so schnell ist die Betonpumpe auch nicht von A nach B geschwenkt!
Davon ab, sehe gerade, in Post #11 hast Du einen Timer-Code - damit sollte sich was machen lassen.

Da das Projekt nicht von einem armen Schüler gebaut wird, sollte der benutzte Stepper ordentlich 'Bumms' haben - zufällig wenig Nennspannung bei ordentlich Strom - DAS wird hier gebraucht?
Jede float-Berechnung braucht UNNÖTIG Zeit.
Siehe Dir dazu Breseham an.
6400 Schritte pro Umdrehung - wie viele Umdrehungen wir pro Sekunde brauchen wurde schon erwähnt? (gerne mit etwas 'Luft nach oben') - würde die Steps/Sekunde liefern, Die der Timer treffen können muß - je Mehr Der kann, desto 'smoothiger' sind die Übergänge bei hohen Geschwindigkeiten.
Bei langsamer Fahrt ist's egal, ob der nächste Step nach 1000 oder 1020µs kommt - macht 2% - von 20 auf 19 schaut's Da schon anders aus.
Wir Dir nicht neu sein, aber je mehr Spannung Du an den Treiber gibst, desto agiler wird der Stepper - der Strom sollte zuvor auf den Stepper eingestellt sein - dem Treiber ist der Stepper egal und Der prügelt Da auch manches Ampere mehr durch, wenn's gewünscht wird.

Vorerst bin ich, glaube, fertig :wink:

MfG

Edit's ... Jesses ... Rechenfehler und Rechtschreibung ... HueteHeute nicht mein Tag ...
Besser?? Besser!! ... Du bist nicht Du, wenn Du laufend editieren musst :wink:

PS:
Habe den Stepper-Code Mal auf einen Nano gepackt und den A0 gegen eine Terminal-Eingabe getauscht.
Terminal-Eingabe entspricht (ganz grob) der Taktfrequenz - also 100 -> 100Hz, 32767 (maximum) -> 32kHz.
In Real 100 -> 96,5Hz und 32767 -> 31,4kHz, was bei 6400 Microstept immer noch knapp über 5 Umdrehungen die Sekunde sind.
Bei der Eingabe von 0 zählt auch die ISR immer nur +0 und ändert damit auch Nichts am Taktausgang.
AUS-Wert 0 -> Takt bleibt so stehen, wie Er gerade steht
MIN-Wert 1 -> 1Hz
MAX-Wert 32767 -> 31,4kHz
Werte über 32767 (bis 65535) verhalten sich wie negative Werte, also rückwärtszählend.
Wobei 32768 <-> 32766
Und 1 <-> 65535

/* //////////////////////// Hardware, Ein- & Ausgangsbelegung  ////////////////////////////////////////////////////////

                     Arduino  OQ PCB                                OQ PCB     Arduino             Verwendung
                     -------  ------           ___________          --------   --------            --------------
                              (RESET)-----PC6 |1        28| PC5----(ADC5,SCL)  Dig19 Ana5
                     Dig0(RX) (RXD)-------PD0 |2  o   i 27| PC4----(ADC4,SCA)  Dig18 Ana4
                     Dig1(TX) (TXD)-------PD1 |3  o   i 26| PC3----(ADC3)      Dig17 Ana3
                     Dig2     (INT0)------PD2 |4  o   i 25| PC2----(ADC2)      Dig16 Ana2
                     Dig3     (INT1)------PD3 |5  o   i 24| PC1----(ADC1)      Dig15 Ana1
                     Dig4     (XCK/TO)----PD4 |6  o   i 23| PC0----(ADC0)      Dig14 Ana0  <======= Sollwertvorgabe
                                          VCC |7  o   o 22| GND
                                          GND |8  o   o 21| AREF
                              (XTAL1)-----PB6 |9  i   o 20| AVCC
                              (XTAL2)-----PB7 |10 i   o 19| PB5----(SCK)       Dig13
                     Dig5,PWM (T1)--------PD5 |11 o   o 18| PB4----(MISO)      Dig12
                     Dig6,PWM (AIN0)------PD6 |12 o   o 17| PB3----(MOSI,OC2)  Dig11,PWM
                     Dig7     (AIN1)------PD7 |13 o   o 16| PB2----(SS,OC1B)   Dig10,PWM
                     Dig8     (ICP1)------PB0 |14 o   o 15| PB1----(OC1A)      Dig 9,PWM   =======> Taktausgang
                                               -----------
*/
//bei 32676 31,4kHz / 31,9µs Periodendauer
//bei 200 190Hz / 5.26ms
//bei 100 96.5Hz / 10.4ms
//übergebene Zahl = HZ
int Taktausgang   = 7 ;  // Digitalausgang 9 = Taktausgang, ist Hardwaremäßig vorgegeben

/////////////////////////// Takterzeugung  //////////////////////////////////////////

volatile uint16_t taktWert = 0;              // Variable für Zählwert 0 - 65535
volatile uint16_t taktSpeed = 1;             // Variable Schrittweite fürs Zählen

SIGNAL(TIMER1_OVF_vect)             // Interruptroutine, wird bei jedem Timerüberlauf aufgerufen
{
  taktWert += taktSpeed;             // taktWert um taktSpeed erhöhen, 16bit, Überlauf bei 65536
  if (taktWert >= 45000)             // Rechteck erzeugen, ist Symmetrisch bei 32768
    digitalWrite(Taktausgang, HIGH);
  else
    digitalWrite(Taktausgang, LOW);
}

//////////////////////// Initialisierung  ///////////////////////////////////////////
void setup()
{
  pinMode(Taktausgang, OUTPUT);        // Taktausgang belegen
  Serial.begin(9600);                  // Kommunikation ermöglichen
  // Timer1 konfigurieren / Registerbits setzen
  TCCR1A = (1 << WGM10) | (1 << COM1A1); // Fast PWM 8 bit | Kanal A rücksetzen wenn gleich
  TCCR1B = (1 << CS10) | (1 << WGM12) ; // Kein Prescaler | Fast PWM 8 bit
  TIMSK1 |= (1 << TOIE1);              // Interruptroutine aktivieren
}
//////////////////////// Programm  //////////////////////////////////////////////////
uint16_t nextspeed = 0;
void loop()
{
  if ( Serial.available() )
  {
    char c = Serial.read();
    if (c >= '0' && c <= '9') {
      nextspeed = nextspeed*10 + c - '0';  //Zahlwert zusammen setzen
    }
    if (c == '\n') {
      noInterrupts();
      taktSpeed = nextspeed;
      interrupts();
      Serial.print("Geschwindigkeit geändert auf ");
      Serial.println(nextspeed);
      nextspeed = 0;
    }
  }
}

Interessantes Video!
Ich dachte allerdings, der Trick bei Stahlbeton ist der Stahl.
(Beton aussendrum ist dafür da, dass der Stahl nicht so schnell rostet)

Wenn ihr soweit seid, Baustahl auch direkt aus 'nem 3D-Drucker auf der Baustelle zu gießen, meldet euch noch mal.