Bij deze presenteer ik de nieuwe besturingssoftware voor de wikkelmachine. Deze kan van 'apenhaar' tot 'van dik hout' maximaal 1mm aan, is de bedoeling.

Ik had een probleem met de aansturing van de draadgeleiderstepper, dat is inmiddels enigszins 'opgelost'. De steppers liepen sowieso wat 'hakkerig'. Dat loopt nu wat soepeler.

Tevens is er/kan nu de draadteller met een 1 cm resolutie heen en terugtellen.

Het inleggen van de draad is nu ook makkelijker omdat de draadgeleiderunit nu aan de rechterkant open is.

de invoer van de wikkeldata gaat nu nog middels de seriële interface van de Arduino IDE of een andere seriële console.

Ik wil in de toekomst wel met een display en rotaryswitsch gaan werken. Echter er komt behoorlijk veel 'monitordata' uit wat niet op een standaard LCD schermpje past.

Dat 'monitoren' hoeft misschien niet en is eenvoudig uit te schakelen indien nodig.

Het kan zijn, zal zeker zo zijn dat sommige zaken programeertechnisch 'onhandig' of inefficent zijn. Ik ben echter geen pro op dat gebied en het is zeker niet m'n sterkste kant.

Nou, oké dan, de gehele code zoals die nu is, ik ben benieuwd. :) :



// Wikkelmachine besturing versie 2_1_1
// Definieer (stepper)motor, steps per 360 graden,
// sensor aansluitingen en stuursignalen.

#include <EEPROM.h>
// Macro's
#define enablestepper 2
#define windingrichting 3
#define windingstap 4
#define draadrichting 5
#define draadstap 6
#define okknop digitalRead(7)
#define draadmeter_A digitalRead(8)
#define draadmeter_B digitalRead(9)
#define draadtensiesensor analogRead(A0) / 10
#define stopsensor analogRead(A1)



// Hardware settings
int Steps = 6400;

// Declaratie globale variabelen

int stopsensorreferentie;
int microsec;
int wikkellichaam;
int wikkellagen;
int totaalwindingen = 1000;  //Voor test en service
int laagwindingen;
int restantwikkelingen;
int draaddiameter = 100;  //Voor test en service
int draadmeterstate;
int draadmeterlaststate;
int draadsteps;
float wikkellichaam_MM = 10;  //Voor test en service
float meterdraad;
float M6micrometergraad;
float motorgraadperstep;
float motormicrometerstep;
float frequentie = 0.001;  //Voor test en service
String pauzeperlaag;


/* Uitleg over hoe ik tot deze berekining kom.
  // De daadwerkelijke berekening gebeurd in berekendata.
  // M6-as is 1mm per 360 graden. 1mm is 1000 micrometer.
  // 1000 gedeeld door 360 is 2.78 micrometer 
  // per graad van de M6-as.
 
  M6micrometergraad = 1000/360.00;

  // 360 graden van de stepper in b.v. fullstepmode
  // is 200 steps. Met 360 gedeeld door 200 is
  // dat 1.8 graden per step.

  motorgraadperstep = 360.00/Steps;

  // 1:5 vertraging tussen stepper en M6-as.
  // inmiddels ben ik overgegaan op 1:1

  // 1.8 graden gedeeld door 5 is 0.36 graden op de M6-as.
  // 1 motorgraadperstep van (1.8 / 5)*0.36 geeft een
  // verplaatsing van 1.0008 micrometer.
  // Afgerond is de motormicrometerstep van 1 step
  // dan 1 micrometer voor de fullstep mode.

  motormicrometerstep = (motorgraadperstep / 5) * M6micrometergraad;

  // Benodigd aantal steps per draaddiameter is dan de
  // draaddiameter gedeeld door de motormicrometerstep per step.

  draadsteps = draaddiameter/motormicrometerstep;
*/


void setup() {
  Serial.begin(115200);
  EEPROM.get(0, stopsensorreferentie);

  //Declare digitale pins als output of input:
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);

  draadmeterlaststate = draadmeter_A;  // init draadmeter.
  invoerwikkeldata();
  berekendata();
  printsetupdata();
  draadgeleiderinit();  // in ontwikkeling
}

void invoerwikkeldata() {
  Serial.print("Geef wikkellichaam breedte in millimeter: ");
  while (Serial.available() == 0);
  wikkellichaam_MM = Serial.parseFloat();
  Serial.println(wikkellichaam_MM);

  Serial.print("Geef aantal wikkelingen: ");
  while (Serial.available() == 0);
  totaalwindingen = Serial.parseInt();
  Serial.println(totaalwindingen);

  Serial.print("Geef draaddiameter in micrometer: ");
  while (Serial.available() == 0);
  draaddiameter = Serial.parseInt();
  Serial.println(draaddiameter);

  Serial.print("Geef wikkelsnelheid in kHz: ");
  while (Serial.available() == 0);
  frequentie = Serial.parseFloat();
  Serial.print(frequentie);
  Serial.println(" kHz");
  
}


void berekendata() {
  // Reken frequentie om naar microseconden
  microsec = (1 / frequentie) * 1000;

  // Bereken aantal steps om de draadgeleider
  // de diameter van de draad te laten verplaatsen.
  M6micrometergraad = 1000 / 360.00;
  motorgraadperstep = 360.00 / Steps;
  //  motormicrometerstep = (motorgraadperstep / 5) * M6micrometergraad;
  // Inmiddels is de 1:5 vervangen voor 1:1 wegens meer
  // ruimte om winding en draadgeleider beter te synchroniseren en
  // dat de draadsteps beter verdeeld worden over de windingsteps.
  motormicrometerstep = motorgraadperstep * M6micrometergraad;
  draadsteps = (draaddiameter / motormicrometerstep);

  // Reken de milimeters van het wikkellichaam
  // om naar micrometers.
  wikkellichaam = wikkellichaam_MM * 1000;

  // Bereken het aantal windingen per wikkellaag.
  laagwindingen = wikkellichaam / draaddiameter;

  // Bereken het aantal wikkellagen.
  wikkellagen = totaalwindingen / laagwindingen;

  // Bereken het aantal restantwikkelingen
  // als die er zijn.
  restantwikkelingen = totaalwindingen % laagwindingen;

  // Correctie voor als er maar 1 wikkellaag is.
  if (wikkellagen < 1) {
    wikkellagen = 1;
    laagwindingen = restantwikkelingen;
    restantwikkelingen = 0;
  }
}

// in ontwikkeling
void draadgeleiderinit() {
  Serial.println("Draadgeleider gaat naar de startpositie <<-");
  digitalWrite(draadrichting, HIGH);
  digitalWrite(enablestepper, HIGH);

  for (int i = 0; i < (laagwindingen / 2); i++) {
    draadstepping();
  }
  digitalWrite(enablestepper, LOW);
  Serial.println("Is de startpositie goed?");
  while (okknop == HIGH);
}

// Meet de hoeveelheid draad met een resolutie van 1 cm.
// Zowel voorwaarts als achterwaarts.
void draadmeter() {
  // Leest de "huidige" staat van draadmeter_A
  draadmeterstate = draadmeter_A;

  // Als er verschil is tussen de vorige en de huidige
  // staat van draadmeter_A, dan was er een puls.
  if (draadmeterstate != draadmeterlaststate) {

    // Als er een puls was en de staat van draadmeter_B
    // niet gelijk is aan draadmeter_A, dan draaide de
    // sensor voorwaarts. Tel 1 cm draad op bij meterdraad.
    if (draadmeter_B != draadmeterstate) {
      meterdraad = meterdraad + 0.01;
    }
    // Indien niet dan draaide de sensor terug en gaat
    // er 1 cm draad af van meterdraad.
    else {
      meterdraad = meterdraad - 0.01;
    }
  }
  // Werkt de vorige staat van draadmeter_A bij
  // met de huidige staat,
  draadmeterlaststate = draadmeterstate;
}

// Maakt een steppuls van 1 microseconde voor de windingmotor.
void windingpuls() {
  digitalWrite(windingstap, HIGH);
  delayMicroseconds(1);
  digitalWrite(windingstap, LOW);
}

// Maakt een steppuls van 1 microseconde voor de draadgeleidermotor.
void draadpuls() {
  digitalWrite(draadstap, HIGH);
  delayMicroseconds(1);
  digitalWrite(draadstap, LOW);
}

// Voor 'service' en debugging.
void printstepperdata() {
  // Initialisatie van de teller voor het aantal
  // stappen van de draadverplaatsings motor.

  int deelfactor = 0;  // verdeelt de draadpulsen gelijkmatig over draadsteps.
  int d = 0;           // bruto draadsteps draadteller;
  int wpuls = 0;       //Windingpuls teller ter vervanging van windingpuls();
  int dpuls = 0;       //Draadpuls teller ter vervanging van draadpuls();

  // De steps teller voor 1 360 graden rotatie
  // van de windingmotor.
  for (int s = 1; s < Steps + 1; s++) {
    deelfactor = s % (Steps / draadsteps);
    // windingpuls();
    wpuls++;
    if (wpuls > Steps) {
      wpuls = 0;
    }

    // Als de trekkracht op de draad te hoog wordt dan
    // noodstop om dat probleem op te losen.
    if (draadtensiesensor > 60) {
      Serial.print("STOP! Draad tensie te hoog: ");
      Serial.println(draadtensiesensor);
      while (okknop == HIGH);
    }

    // Als teller d kleiner is dan het aantal
    // draadsteps en deelfactor is nul, tel er 1 bij op
    // en geef de draadmotor 1 stap.
    if (d < draadsteps && deelfactor == 0) {
      d++;
      if (d > draadsteps) {
        d = 0;
      }
      // draadpuls();
      dpuls++;
      if (dpuls > draadsteps) {
        dpuls = 0;
      }
    }

    // Vertraging om de frequentie van de stepperpulsen
    // te regelen.
    delayMicroseconds(microsec);

    // Meet hoeveel draad er is gebruikt.
    //draadmeter();
    Serial.print("Steps:");
    Serial.print(Steps);
    Serial.print(" Steps teller:");
    Serial.print(s);
    Serial.print(" windingpuls teller:");
    Serial.print(wpuls);
    Serial.print(" draadsteps:");
    Serial.print(draadsteps);
    Serial.print(" draadsteps teller:");
    Serial.print(d);
    Serial.print(" draadpuls teller:");
    Serial.print(dpuls);
    Serial.print(" deelfactor:");
    Serial.print(deelfactor);

    /*
    Serial.print(Steps);
    Serial.print("\t");
    Serial.print(s);
    Serial.print("\t");
    Serial.print(draadsteps);
    Serial.print("\t");
    Serial.print(d);
    Serial.print("\t");
    Serial.print(e);
  */
    Serial.println();
  }
}

// regelt het aansturen van alleen de draadstapmotor.
void draadstepping() {
  // Initialisatie van de teller voor het aantal
  // stappen van de draadverplaatsings motor.
  int d = 0;  // bruto draadsteps draadteller;
  int deelfactor = 0;  // verdeelt de draadpulsen gelijkmatig over draadsteps.

  // De steps teller voor 1 360 graden rotatie
  // van de motor.
  for (int s = 1; s < Steps + 1; s++) {
    deelfactor = s % (Steps / draadsteps);
    // Als teller d kleiner is dan het aantal
    // draadsteps en deelfactor is nul, tel er 1 bij op
    // en geef de draadmotor 1 stap.
    if (d < draadsteps && deelfactor == 0) {
      d++;
      if (d > draadsteps) {
        d = 0;
      }
    draadpuls();
    }

    // Vertraging om de frequentie van de stepperpulsen
    // te regelen.
    delayMicroseconds(microsec);
  }
}

// regelt het aansturen van de stappenmotoren.
void stepping() {
  // Initialisatie van de teller voor het aantal
  // stappen van de draadverplaatsings motor.

  int deelfactor = 0;  // verdeelt de draadpulsen gelijkmatig over draadsteps.
  int d = 0;           // bruto draadsteps draadteller;

  // De steps teller voor 1 360 graden rotatie
  // van de windingmotor.
  for (int s = 1; s < Steps + 1; s++) {
    deelfactor = s % (Steps / draadsteps);
    windingpuls();

    // Als de trekkracht op de draad te hoog wordt dan
    // noodstop om dat probleem op te losen.
    if (draadtensiesensor > 60) {
      Serial.print("STOP! Draad tensie te hoog: ");
      Serial.println(draadtensiesensor);
      while (okknop == HIGH);
    }

    // Als teller d kleiner is dan het aantal
    // draadsteps en deelfactor is nul, tel er 1 bij op
    // en geef de draadmotor 1 stap.
    if (d < draadsteps && deelfactor == 0) {
      d++;
      if (d > draadsteps) {
        d = 0;
      }
      draadpuls();
    }

    // Vertraging om de frequentie van de stepperpulsen
    // te regelen.
    delayMicroseconds(microsec);

    // Meet hoeveel draad er is gebruikt.
    draadmeter();
  }
}

// Geeft de uitkomsten van de berekeningen weer.
void printsetupdata() {
  Serial.println();
  Serial.print("Het aantal wikkellagen is: ");
  Serial.print(wikkellagen);
  Serial.println(".");
  Serial.print("Het aantal windingen per laag is: ");
  Serial.print(laagwindingen);
  Serial.println(".");
  Serial.println();
  if (restantwikkelingen != 0) {
    Serial.print("Het restant van wikkelingen is ");
    Serial.println(restantwikkelingen);
    Serial.print("windingen op 1 extra windinglaag");
    Serial.println();
    Serial.print("Het totaal aantal wikkellagen is nu ");
    Serial.print(wikkellagen+1);
    Serial.println(".");
  }
  Serial.println("Oké?");
  while (okknop == HIGH);
}
// Als laagwindingen * wikkellagen < W
// Geeft realtime weer welke wikkelingen en lagen gedaan zijn.
void printwikkeldata(int W, int L, int WL) {
  Serial.print("Uitgevoerd:");
  Serial.print(W);
  Serial.print(" windigen van:");
  Serial.print(totaalwindingen);
  Serial.print(" waarvan:");
  Serial.print(L);
  Serial.print(" laagwindingen van:");
  if ((laagwindingen * wikkellagen) > W) {
    Serial.print(laagwindingen);
  }
  else {
    Serial.print(restantwikkelingen);
  }
  Serial.print(" op laag:");
  Serial.print(WL);
  Serial.print(" van:");
  if (restantwikkelingen != 0) {
    Serial.print(wikkellagen+1);
  }
  else {
    Serial.print(wikkellagen);
  }
  Serial.print(". Draadgeleider richting:");
  if (WL % 2 == 0) {
    Serial.print(" <-");
  } else {
    Serial.print(" ->");
  }
  Serial.print(". Meters draad:");
  Serial.print(meterdraad);
  Serial.print(". Draadtensie: ");
  Serial.println(draadtensiesensor);
}


void loop() {
  int L = 1;   // laagwindingen teller.
  int WL = 1;  // lagen teller.

  Serial.print("Uitvoeren?");
  while (okknop == HIGH);
  digitalWrite(enablestepper, HIGH);
  Serial.println(" Oké");
  // Telt totaalwindingen
  for (int W = 0; W < totaalwindingen; W++) {
    // winding per laag teller.
    if (L > laagwindingen) {
      L = 1;
      WL++;
    }
    // Bepalen of het een even of oneven laag is voor
    // de besturing van de richting.
    if (WL % 2 == 0) {
      digitalWrite(draadrichting, HIGH);
    } else {
      digitalWrite(draadrichting, LOW);
    }
    // Uitvoeren van de stappen.
    stepping();
    printwikkeldata(W + 1, L, WL);
    //printstepperdata(); //Voor service en debugging.
    L++;
  }

  // Klaar, uitschakelen steppers
  digitalWrite(enablestepper, LOW);
  while (okknop == HIGH);
  delay(1000);
}

```

Het ziet er uit als een mooi programma. Maar verder kan ik er niet veel van zeggen omdat ik geen idee heb over wel wikkelmachientje hier gesproken wordt?

Wat is 'de wikkelmachine'

Ik krijg een paar honderd mogelijkheden als ik dit invul in een zoekmachine.

Wilde je dit zomaar delen of wil je feedback?

De eerste tip die ik je wil geven: Zo min mogelijk commentaar!
Ja je hoort het goed, het gaat tegen alle docenten in, maar zo MIN mogelijk commentaar.

Heel simpel voorbeeld:


void loop() {
  int L = 1;   // laagwindingen teller.
  int WL = 1;  // lagen teller.

Dit zou ik aanpassen naar:


void loop() {
  int gewenstAantalLagen= 1; 
  int actueelAantalLagen= 1;

Waarom?
Je code is geeft nu aan wat er gebeurt. Ook verderop in de code weet ik niet meer wat WL was. Maar wel wat actueelAantalLagen betekent. Daarnaast kan door verloop van tijd je commentaar niet meer kloppen met de code.
Met andere woorden, de code klopt altijd met wat er gebeurt. Commentaar niet. Zorg ervoor dat de code te lezen is voor mensen. De processor doet toch wel wat er staat.

Dit is een persoonlijke voorkeur, maar ik zou er voor kiezen om in het Engels te werken.

Er is meer feedback die ik je zou willen geven, maar ik wacht eerst even af of je daar wel op zit te wachten :)

Knap gemaakt !!
Is mijn eerste gedachtenkronkel na het bekijken van de twee filmfragmenten.
Ook het 'danser mechanisme' om de trekkracht op de draad te meten is leuk gevonden.

Als ik mag toch twee gedachtenkronkels

- 1) vermoedelijk gebeurt het oprollen nu op basis van het maximaal beschikbaar koppel van je aandrijfmotor.
Is het een meerwaarde als je het oprollen laat gebeuren op basis van een instelbaar koppel ?
Met andere woorden je trekt aan de draad met een gelijke kracht waarvan het maximum instelbaar is.
Dit heeft waarschijnlijk voordelen indien je een lange platte transformator kern moet wikkelen

- 2) als je een eerste "laag" gewikkeld hebt, wil je over die eerste laag een tweede laag wikkelingen leggen. Als je geen transformatorkern hebt die bewikkeld wordt, merk je dat de draad de neiging heeft verder te wikkelen in plaats van naar de reeds gewikkelde laag te gaan.
Een hol buisje dat de draad geleidt en dicht tegen de gewikkelde spoel aandraait kan dit oplossen, zonder dat dit een beperking inhoudt voor de grootte van de te wikkelen spoelen.

int gewenstAantalLagen= 1;
int actueelAantalLagen= 1;

IK zou dan zelf als variatie nemen
actueleLagen en gewensteLagen omdat het toch wel duidelijk is het om aantallen gaat.

Maar voorkom van dit soort korte variabelen die als het programma groter word dan toch voor twijfel zorgen.

[Bericht gewijzigd door benleentje op (22%)]

Voor functies:
Hoe specifieker (kleinere scope) hoe langer de naam.
Hoe globaler (grote scope) korte naam.

Voorbeelden grote scope: strlen, memcpy, msToFreq
Kleine scope: StepMotorAndVerifyEncoder

Voor variabelen is dit precies andersom:
In een kleine scope is 'i' best prima om iterator aan te geven.
Maar voor een grote scope is 'i' heel vaag. Dan heb je liever: MaximaalAantalWindingenPerLaag.

---
Ik heb het wel met je eens, actueleLagen en gewensteLagen is nog mooier.

Als je ziet waarmee het begonnen is (https://www.circuitsonline.net/forum/view/169521), dan is dit toch wel een hele verbetering. Dit is ook voor een buitenstaander redelijk makkelijk te volgen. Dus heel goed. :)

Op dinsdag 29 juli 2025 17:51:03 schreef deKees:
dan is dit toch wel een hele verbetering.

_/-\o_ _/-\o_

Maar wat hardbass zegt daar leer ik ook weer van en de namen van functies moeten ook duidelijk zijn heb ik daarvan geleerd.

Op dinsdag 29 juli 2025 12:12:30 schreef hardbass:

De eerste tip die ik je wil geven: Zo min mogelijk commentaar!
Ja je hoort het goed, het gaat tegen alle docenten in, maar zo MIN mogelijk commentaar.

Hier ben ik het niet zo mee eens. Als ik zelf niet ook veel commentaar in software zet weet ik na een jaar niet meer wat ik bedacht heb. Als ik 5000 regels code heb wil ik daar toch graag flinke blokken commentaar tussen hebben, anders kan ik later nooit meer even snel een aanpassing maken.

Redelijk wat commentaar erbij is aan te raden (in Engels, da's makkelijk voor posten op buitenlandse forums)

Wel zinvol commentaar. Ik erger me altijd vreselijk aan:
- onnodig commentaar. bijv i = i + 1 en dan erachter zetten 'one added to i' ... :(
- commentaar niet aanpassen als de code wijzigt. Vaak blijft het oude commentaar dan staan en slaat nergens meer op...

Ja je hoort het goed, het gaat tegen alle docenten in, maar zo MIN mogelijk commentaar.

Zinloze commentaar zoals de nu de led aanzetten, nu de ventilator uitzetten sla ik ook over. Ben wel met je eens als je variabele en functie omschrijven duidelijk zijn is er niet zo veel commentaar nodig is.

Het liefst zet ik commentaar voor een functie of regel, maar commentaar achter een regel doe ik maar zelden.

Waar ik later achter kwam met mijn arduino projecten is een beschrijven van de gebruikte modules, de kleuren draad en hun functie en op welke pin.

Iedereen bedankt voor de adviezen. Ik ga weer even aan de gang met de adviezen. :)

Op dinsdag 29 juli 2025 15:54:23 schreef pamwikkeling:
Knap gemaakt !!
Is mijn eerste gedachtenkronkel na het bekijken van de twee filmfragmenten.
Ook het 'danser mechanisme' om de trekkracht op de draad te meten is leuk gevonden.

Als ik mag toch twee gedachtenkronkels

- 1) vermoedelijk gebeurt het oprollen nu op basis van het maximaal beschikbaar koppel van je aandrijfmotor.
Is het een meerwaarde als je het oprollen laat gebeuren op basis van een instelbaar koppel ?
Met andere woorden je trekt aan de draad met een gelijke kracht waarvan het maximum instelbaar is.
Dit heeft waarschijnlijk voordelen indien je een lange platte transformator kern moet wikkelen

Lijkt mij fantastisch. Ik heb alleen geen flauw idee hoe de trekkracht van de stepper te sturen zonder stappen te verliezen.

Het huidige instrumentje met de Hall sensoren is min of meer beperkt tot (veel) "te hoog" en eventueel een "te laag". Het werkt wel goed om obstructie te detecteren zonder dat de draad breekt omdat de steppers dan onmiddellijk stoppen. Ook draadbreuk of i.i.g. (veel) te lage trekspanning kan nog wel gedetecteerd worden.

- 2) als je een eerste "laag" gewikkeld hebt, wil je over die eerste laag een tweede laag wikkelingen leggen. Als je geen transformatorkern hebt die bewikkeld wordt, merk je dat de draad de neiging heeft verder te wikkelen in plaats van naar de reeds gewikkelde laag te gaan.
Een hol buisje dat de draad geleidt en dicht tegen de gewikkelde spoel aandraait kan dit oplossen, zonder dat dit een beperking inhoudt voor de grootte van de te wikkelen spoelen.

Dat over dat buisje/tuitje is een goede opmerking. Ik ga eens nadenken over hoe ik dat vorm kan geven.

Op dinsdag 29 juli 2025 17:51:03 schreef deKees:
Als je ziet waarmee het begonnen is (https://www.circuitsonline.net/forum/view/169521), dan is dit toch wel een hele verbetering. Dit is ook voor een buitenstaander redelijk makkelijk te volgen. Dus heel goed. :)

Ik heb nu recentelijk de Arduino IDE 2.3.6 geïnstalleerd en begrijp nu wat je bedoelde met o.a. die rommelige indent.. :P

Voor nu moet ik ook nog even e.e.a. uitzoeken rond de int's, float's e.d. want daar gaat e.e.a. niet goed omdat een aantal getallen waarschijnlijk te groot worden.

Lijkt mij fantastisch. Ik heb alleen geen flauw idee hoe de trekkracht van de stepper te sturen zonder stappen te verliezen.

In principe is het koppel instelbaar via de stroom. Maar je gaat zonder encoder op de stepper nooit weten of je een stap verliest, maar dat weet je nu eigenlijk ook niet toch? Ik neem aan dat je erop gokt dat stepper meer dan sterk genoeg is.

Om de 'slack' op te vangen zetten ze er vaak een extra tussenwiel met veer tussen om onregelmatigheden op te vangen en de draad altijd gespannen te houden.
Waarom stopt 'ie bij iedere omwenteling even? (dat schokken kun je met een meer soepele doorgaande loop voorkomen)

Hier een klein voorbeeldje van wat ik bedoel. Let wel op, dit zal niet werken, er mist een hoop. Het gaat puur om het demonstreren dat je code zo kan schrijven dat commentaar overbodig wordt. Je ziet dat overal waar eerst een comment stond, het nu duidelijk wordt gemaakt door een extra functie of een extra variabele toe te voegen.

@deKees, helemaal mee eens, dit is echt al veel beter dan waar het in dat topic initieel over ging. Chapeau voor TS om al zo ver te komen. Laat duidelijk zijn dat deze post niet bedoeld is om kritiek te leveren of te zeggen dat het beter moet. Het is puur bedoeld om te laten zien hoe je door goede naamgeving en kleine functies je code een stuk begrijpelijker kunt maken.


// This seems overkill, but it makes the code more readable 
bool IsEven(int value) {
    return (value % 2) == 0;
}

// Also for direction, instead of a boolean or int, this is undoubely clear whats going on.
enum Direction
{
    DIRECTION_FORWARD,
    DIRECTION_BACKWARD
};

// By keeping functions very small, its always very easy to see whats going on.
// Even for something as simple as this, an extra function can make it more readable later on.
Direction GetDirectionForLayer(int layer)
{
    // Here you can see the benefit of the IsEven, its more clear than "if ((value % 2) == 0)...."
    if (IsEven(layer)) {
        return DIRECTION_FORWARD;
    } else {
        return DIRECTION_BACKWARD;
    }
}

int GetNumberOfTurnsForLayer(int layer)
{
	// Here I use an extra variable, just for making clear what this expression is supposed to be.
	// If you place the expression directly in the if statement, it obfuscates it a bit.
    bool isLastLayer = (layer == totalLayerCount - 1);
	bool isLastTurn = remainingTurns <= 0;

    if (!isLastLayer)
        return turnsPerLayer;

    if (isLastTurn)
        return turnsPerLayer;

    return remainingTurns;
}

// Because of the enum, its very clear whats going on. I dont have to remember things like: was 1 forward or backward?
void SetWindingDirection(Direction direction)
{
    if (direction == DIRECTION_FORWARD) {
        digitalWrite(wireDirectionPin, HIGH);
    } else {
        digitalWrite(wireDirectionPin, LOW);
    }
}

void ProcessTurn(int layer, int turnIndex)
{
	// By using these functions, i can simply read what it does. 
	// No need for comments to tell me.
	ExecuteWindingStepCycle();
	UpdateWireLengthEstimate();
	CheckWireTensionOrPause();
	DisplayTurnProgress(layer, turnIndex);
}

void ProcessLayer(int layer)
{
	// Now that we have all the 'simple' functions, we can just read what is happening here.
	// The function names should only be interpetable in a single way.
	
    Direction direction = GetDirectionForLayer(layer);
    SetWindingDirection(direction);

	// The variable name can be short, since the function is small its still obvious what this varable does.
    int numberOfTurns = GetNumberOfTurnsForLayer(layer);

	// The scope is so small, even the name 'turnIndex' could become something like 'turn' or even 'i'
    for (int turnIndex = 0; turnIndex < numberOfTurns; turnIndex++) {
		ProcessTurn(layer, turnIndex);
    }
}

// This helps to keep the main clean.
void ProcessAllLayers()
{
    for (int layerIndex = 0; layerIndex < totalLayerCount; layerIndex++) {
        ProcessLayer(layerIndex);
    }
}

// Again, i can see by the names of the functions what happens
void loop()
{
    WaitForStartButton();

    GetUserInput();
    CalculateParameters();

    EnableMotors();
    MoveWireGuardToStartPosition();

    ProcessAllLayers();

    DisableMotors();
}

@TS: je include eeprom.h maar je lijkt het (nog) nergens te gebruiken. Hoe vaak denk je naar eeprom te schrijven? Is dat slechts een paarkeer, geen probleem. Is dat zeer vaak, is FRAM misschien een betere keuze.

Je schrijft ook dat je problemen hebt met bepaalde variabelen. Vele van je variabelen zullen nooit een negatieve waarde aannemen of het is alleszins de bedoeling dat ze dat niet doen. Declareer ze dan als unsigned. Bijvoorbeeld int8_t geeft een waarde tussen -127 en +127 weer. Het achtste bit wordt gebruikt voor positief of negatief. uint8_t loopt van 0 tot 255. Persoonlijk prefereer ik ook de grootte van de variabele aan te geven. uint8_t, int16_t, uint32_t, .....

Op woensdag 30 juli 2025 10:33:20 schreef buckfast_beekeeper:
@TS: je include eeprom.h maar je lijkt het (nog) nergens te gebruiken. Hoe vaak denk je naar eeprom te schrijven? Is dat slechts een paarkeer, geen probleem. Is dat zeer vaak, is FRAM misschien een betere keuze.

Je schrijft ook dat je problemen hebt met bepaalde variabelen. Vele van je variabelen zullen nooit een negatieve waarde aannemen of het is alleszins de bedoeling dat ze dat niet doen. Declareer ze dan als unsigned. Bijvoorbeeld int8_t geeft een waarde tussen -127 en +127 weer. Het achtste bit wordt gebruikt voor positief of negatief. uint8_t loopt van 0 tot 255. Persoonlijk prefereer ik ook de grootte van de variabele aan te geven. uint8_t, int16_t, uint32_t, .....

Daar sluit ik me helemaal bij aan. Het probleem met de types zoals int is dat dit afhankelijk is van het platform. Als je code kopieert naar een ander systeem kan een int ineens nog maar 2 bytes zijn bijvoorbeeld. Dan gaan er dingen stuk. Met int32_t is het altijd hetzelfde.

Op woensdag 30 juli 2025 10:33:20 schreef buckfast_beekeeper:
@TS: je include eeprom.h maar je lijkt het (nog) nergens te gebruiken. Hoe vaak denk je naar eeprom te schrijven? Is dat slechts een paarkeer, geen probleem. Is dat zeer vaak, is FRAM misschien een betere keuze.

Je schrijft ook dat je problemen hebt met bepaalde variabelen. Vele van je variabelen zullen nooit een negatieve waarde aannemen of het is alleszins de bedoeling dat ze dat niet doen. Declareer ze dan als unsigned. Bijvoorbeeld int8_t geeft een waarde tussen -127 en +127 weer. Het achtste bit wordt gebruikt voor positief of negatief. uint8_t loopt van 0 tot 255. Persoonlijk prefereer ik ook de grootte van de variabele aan te geven. uint8_t, int16_t, uint32_t, .....

Dat is goede info over de variabelen, dank daarvoor. Het bleek dat i.i.g. het omrekenen van wikkellichaam millimeters een -float- naar micrometers, de waarde numeriek te groot werd voor de float die de micrometers kreeg toegewezen met mm x 1000. Deze is omgezet naar long en werkt nu wel.

In de eerste versie werd de analoge waarde van een hallsensor 'eenmalig' naar de eeprom geschreven. Deze waarde diende als eindstop en referentie van de draadgeleider en werd opgehaald bij opstarten of een hardware reset van de processor. Echter bleek dat de waarde van de hallsensor te onstabiel is. Deze varieerde tussen 250 en 400 over de dag(en). Ik ga een eindstopschakelaar gebruiken. eeprom.h en aanverwanten gaat er dus uit.

Op dinsdag 29 juli 2025 19:54:15 schreef Arco:
Om de 'slack' op te vangen zetten ze er vaak een extra tussenwiel met veer tussen om onregelmatigheden op te vangen en de draad altijd gespannen te houden.
Waarom stopt 'ie bij iedere omwenteling even? (dat schokken kun je met een meer soepele doorgaande loop voorkomen)

Dat kwam omdat in de eerste versie eerst de ene an dan de andere stepper te sturen waardoor ze op elkaar moesten wachten.

Dat is inmiddels opgelost door beide de pulsen voor de draadgeleidermotor te verdelen over het totale aantal steps van de windingmotor en deze in 1 steppingproces gelijktijdig te genereren.


// regelt het aansturen van de stappenmotoren.
void stepping() {
  // Initialisatie van de teller voor het aantal
  // stappen van de draadverplaatsings motor.

  int deelfactor = 0;  // verdeelt de draadpulsen gelijkmatig over draadsteps.
  int d = 0;           // bruto draadsteps draadteller;

  // De steps teller voor 1 360 graden rotatie
  // van de windingmotor.
  for (int s = 1; s < Steps + 1; s++) {
    deelfactor = s % (Steps / draadsteps);
    if (windingmotor == true) {
      windingpuls();
    }

    // Als de trekkracht op de draad te hoog wordt dan
    // noodstop om dat probleem op te losen.
    if (draadtensiesensor > 60) {
      Serial.print("STOP! Draad tensie te hoog: ");
      Serial.println(draadtensiesensor);
      while (okknop == HIGH);
    }

    // Sturing voor het wikkelen.
    // Als teller d kleiner is dan het aantal
    // draadsteps en deelfactor is nul, tel er 1 bij op
    // en geef de draadmotor 1 stap tijdens het wikkelen.
    if (d < draadsteps && deelfactor == 0 && windingmotor == true) {
      d++;
      if (d >= draadsteps) {
        d = 0;
      }
      draadpuls();
    }

    // Snelle verplaatsing van de draadgeleider
    // naar begin van de wikkelpositie.
    if (d < draadsteps && windingmotor == false) {
      d++;
      if (d >= draadsteps) {
        d = 0;
        s= Steps;
      }
      draadpuls();
    }

    // Vertraging om de frequentie van de stepperpulsen
    // te regelen.
    delayMicroseconds(microsec);

    // Meet hoeveel draad er is gebruikt.
    draadmeter();
  }
}

Is het de bedoeling dat er 2 keer "while (okknop == HIGH);" in de loop staat?

Zou ik niet doen, werkt verwarrend.

Op dinsdag 29 juli 2025 12:12:30 schreef hardbass:
Wilde je dit zomaar delen of wil je feedback?

De eerste tip die ik je wil geven: Zo min mogelijk commentaar!
Ja je hoort het goed, het gaat tegen alle docenten in, maar zo MIN mogelijk commentaar.

Heel simpel voorbeeld:


void loop() {
  int L = 1;   // laagwindingen teller.
  int WL = 1;  // lagen teller.

Dit zou ik aanpassen naar:


void loop() {
  int gewenstAantalLagen= 1; 
  int actueelAantalLagen= 1;

Waarom?
Je code is geeft nu aan wat er gebeurt. Ook verderop in de code weet ik niet meer wat WL was. Maar wel wat actueelAantalLagen betekent. Daarnaast kan door verloop van tijd je commentaar niet meer kloppen met de code.
Met andere woorden, de code klopt altijd met wat er gebeurt. Commentaar niet. Zorg ervoor dat de code te lezen is voor mensen. De processor doet toch wel wat er staat.

Dit is een persoonlijke voorkeur, maar ik zou er voor kiezen om in het Engels te werken.

Er is meer feedback die ik je zou willen geven, maar ik wacht eerst even af of je daar wel op zit te wachten :)

Bij deze aangepast en dat is een stuk duidelijker i.d.d. :)

Feedback is altijd goed.


// Geeft realtime weer welke wikkelingen en lagen gedaan zijn.
void printwikkeldata(int windingteller, int laagwindingteller, int lagenteller) {
  Serial.print("Uitgevoerd:");
  Serial.print(windingteller);
  Serial.print(" windigen van:");
  Serial.print(totaalwindingen);
  Serial.print(" waarvan:");
  Serial.print(laagwindingteller);
  Serial.print(" laagwindingen van:");
  if ((laagwindingen * wikkellagen) >= windingteller) {
    Serial.print(laagwindingen);
  }
  else {
    Serial.print(restantwikkelingen);
  }
  Serial.print(" op laag:");
  Serial.print(lagenteller);
  Serial.print(" van:");
  if (restantwikkelingen != 0) {
    Serial.print(wikkellagen+1);
  }
  else {
    Serial.print(wikkellagen);
  }
  Serial.print(". Draadgeleider richting:");
  if (lagenteller % 2 == 0) {
    Serial.print(" <-");
  } else {
    Serial.print(" ->");
  }
  Serial.print(". Meters draad:");
  Serial.print(meterdraad);
  Serial.print(". Draadtensie: ");
  Serial.println(draadtensiesensor);
}

En:


void wikkelen () {
  int laagwindingteller = 1;
  int lagenteller = 1;

  Serial.print("Uitvoeren?");
  while (okknop == HIGH);
  digitalWrite(enablestepper, HIGH);
  Serial.println(" Oké");
  // Telt totaalwindingen
  for (int windingteller = 0; windingteller < totaalwindingen; windingteller++) {
    // winding per laag teller.
    if (laagwindingteller > laagwindingen) {
      laagwindingteller = 1;
      lagenteller++;
    }
    // Bepalen of het een even of oneven laag is voor
    // de besturing van de richting.
    if (lagenteller % 2 == 0) {
      digitalWrite(draadrichting, HIGH);
    } else {
      digitalWrite(draadrichting, LOW);
    }

    stepping();
    printwikkeldata(windingteller + 1, laagwindingteller, lagenteller);
    laagwindingteller++;
  }

  // Klaar, uitschakelen steppers
  digitalWrite(enablestepper, LOW);
  Serial.println("Klaar.");
  delay(100);
}

Leuk dat je deze hebt verwerkt in je code.

Eerst moest ik uitzoeken wat de code deed om te achterhalen wat deze variabelen betekenen. Dit is nu veel duidelijker.

Om de code nog leesbaarder te maken, begin elk nieuw woord in je variabele met een hoofdletter. Bijvoorbeeld:

laagWindingTeller ipv laagwindingteller

. Constanten schrijf ik meestal in hoofdletters en een underscore tussen de woorden. Bijvoorbeeld

const uint16_t STEPS_REVOLUTION = 6400;

Ook dat is een goede qua structuur. Voorheen maakte ik er afkortingen van dus: lwt of LWT voor laagwindingteller. Maar ik merkte al dat ik met de huidige code soms namen van variabelen, constanten en functies door elkaar ging gebruiken, wat dus foutmeldingen of verkeerde uitvoer van code tot gevolg heeft.

Ondertussen de while okknop ook ondergebracht in een functie.


// Wacht op bevestiging input door gebruiker
// en ontdendering middels delay van 100 mS.
void jaknop() {
  Serial.println("Oké?");
  while (okknop == HIGH);
  delay(100);
}

[Bericht gewijzigd door harry64 op (31%)]