BeneluxSpoor.net forum
Vraag en antwoord => Elektronica en analoog => Topic gestart door: keesg op 29 July 2025, 12:39:30
-
Hallo allemaal,
Ben op zoek naar een schets voor arduino uno voor een snelheid regelaar volgens het Weistra principe. PWM met een veranderende frequentie.
Heb met AI van alles geprobeerd maar krijg geen goede regeling. De trein stopt als ik de snelheid potmeter te snel van langzaam naar snel draai. Duurt een 0.5 sec en rijd dan weer verder.
Ik krijg dit probleem niet weg.
Ik heb geen verstand van programmeren maar weet wel een beetje wat een arduino doet.
Ik zoek een regeling met 1 potmeter voor de snelheid en een schakelaar voor de rijrichting. Mijn arduino is aangesloten op een L298n motor driver.
De arduino en L298n printjes zijn van Chinese afkomst. klonen dus.
Zijn er mensen die de regeling hebben gemaakt en mij een schets kunnen sturen?
-
Iemand op dit forum heeft de Weistra regelaar al eens in software gebouwd, ik dacht bask, maar dat kan ik mis hebben.
Wat is voor jou de reden om het met een Arduino te doen? Als je wil besturen met een potmeter en een schakelaar, dan is een hardware schakeling vrij eenvoudig te maken.
-
Hallo Klaas.
Ik heb de regeling van Weistra ook analoog gebouwd. Van elektronica heb ik wel kennis. Deze werkt voor mijn Fleischmann treinen perfect.
Ik wil er een aantal hebben en prijs technisch gezien is het interessant om het met een arduino te doen. Vooral de nano is interessant maar die heb ik niet in huis.
Dus eerst proberen met de UNO. AI werkt heel goed maar dat stoppen is hopeloos.
Vandaar.
-
Maakt het prijstechnisch echt veel verschil? Een hardware versie kost een tientje aan onderdelen. De duurste delen zijn de potmeter, de schakelaar en de powertransistor, en die heb je bij de Arduino versie ook nodig.
-
In het algemeen zou ik zeggen: gebruik je een Arduino zet dan ook de sketch in de vraag. Laatste tijd vraag ik AI ook om de aanzet tot een sketch maar moet er wel vaker fouten uit halen.
-
Klopt wat je zegt maar ik wil met de arduino nog veel meer dingen doen. AI werkt erg goed. Heb ik ook voor andere dingen gebruikt die erg goed werken. Zoals bv aan stappen motor.
Het is ook een uitdaging om te kijken of het met een arduino lukt. Ben van plan er een stuk of 10 aan te schaffen ook voor andere doeleinden. Alleen het programmeren in C is erg lastig en het leren kost veel tijd. Vroeger wel veel geprogrammeerd met de 8085 processor maar dat gaat niet met C maar op een hexadecimale manier.
Helaas laat AI nu mij in de steek daarom de vraag. Ik zal niet de enige zijn die daar mee aan de gang is gegaan.
Het is alleen een schets. Voor de deskundige zal het wel te doen zijn denk ik.
-
Ik had gevraagd de sketch te delen om mee te denken. ???
-
Guilty!
Je hebt de weistra.cpp en weistra.h nodig. Je moet in je project folder waar je .ino staat deze 2 bestanden toevoegen. Om te downloaden kan je het makkelijkst de gehele respository downloaden. Op de code knop klikken en dan download zip. En modules folder staan de bestanden die je zoekt.
https://github.com/bask185/ArduinoToolchain (https://github.com/bask185/ArduinoToolchain)
https://github.com/bask185/ArduinoToolchain/tree/master/modules (https://github.com/bask185/ArduinoToolchain/tree/master/modules)
Wat betreft de sketch. Ik denk dat dit moet werken
#include "weistra.h"
const int pinA = 2 ;
const int pinB = 3 ;
const int Fmin = 50 ;
const int Fmax = 100 ;
const int CS = A0 ;
const int potPin = A1 ;
const int acceleration = 500 ;
const int potMiddle = 512 ;
const int deadRange = 20 ;
Weistra pwm( pinA, pinB, Fmin, Fmax ) ;
void setup()
{
pinMode( potPin, INPUT ) ;
pwm.begin() ;
uint8_t currentLimit = 169 ;
/*currentLimit = Imax * Rshunt / 0.00488 -> 2.5A x 0.33R (3x 1R parallel) / 0.00488 = 169 */
pwm.setCurrentSense( CS, currentLimit )
}
void loop()
{
static uint32_t lastTime = 0 ;
if( millis() - lastTime >= acceleration ) // run every interval time
{ lastTime = millis() ;
static int8_t throttle = 0 ;
int8_t setPoint = 0 ;
int sample = analogRead( potPin ) ;
if( sample <= potMiddle - deadRange ) setPoint = map( sample, 0, potMiddle - deadRange , -100, 0 ) ; // scale [0.. middle -20] to [-100..0]
else if( sample >= potMiddle + deadRange ) setPoint = map( sample, potMiddle + deadRange , 1023, 0, 100 ) ; // scale [middle + 20 .. 1023] to [0..100]
else setPoint = 0 ; // middle 40 adc steps = dead range -> speed 0
if( throttle < setPoint ) throttle ++ ;
if( throttle > setPoint ) throttle -- ;
pwm.setSpeed( throttle ) ;
}
pwm.update() ; // also handles short circuit.
}
Er zit ook kortsluiting detectie en autoreset ingebouwd. De L298 is niet beveiligd tegen sluiting. Je kan tussen de GND pin en de voeding 3 of 4 1R weerstanden parralel (en een 100nF condensator) zetten, of een dikkere weerstand met een lage waarde 0.1R - 0.33R. Er moet dan ook een draadje naar een analoge ingang (CS) De weerstand moet wel de stroom kunnen dissiperen. De berekening in code van wat je stroom grens moet zijn, staat in commentaar. Zo kan je zelf kiezen hoeveel stroom je maximaal wilt kunnen uitsturen.
De enable pin mag aan de 5V en beide ingang pinnen van een van de 2 kanalen mogen aan outputs naar keuze.
De code leest de potmeter in, maakt een dood gebiedje om makkelijk je trein stil te kunnen zetten (anders is dat niet te doen) en schaalt de potmeter waarde correct om naar gebruik voor de weistra. Er zit een optrek rem vertraging in, die kan je instellen met 'acceleration'. Lage waarde = kleine optrek/rem vertraging.
Je kan ook Fmin en Fmax instellen. Zelf vind ik 20Hz kut om 2 redenen, 50Hz raad ik aan als onder grens en 100Hz als boven grens.
Mvg,
Bas
-
Hoi Bask,
Nu kom ik wat verder. Ik hoop dat ik het allemaal begrijp. Uhh.....de eerste regel is al lastig. de stroombeveiliging snap ik wel.
Denk dat ik toch iets meer hulp nodig heb.
Kan wel een schets downloaden enz.
-
Nee Bask ik zie nu door de bomen even het bos niet meer.
Help !!!!
-
Ik kan vanavond wel ff helpen. Dan maak ik wel ff een filmpje
-
fijn dat je wilt helpen. Elektronica lukt wel maar programmeren van een arduino is een ander verhaal.
Ik was blij met AI maar dat lukt niet echt.
Hopelijk kan je me duidelijk maken hoe ik de arduino kan programmeren.
-
Ik heb trouwens een Chinese kloon van de arduino UNO.
-
https://www.youtube.com/v/aEzPoUzBphE
-
Dank je wel voor het filmpje
Erg vriendelijk om dat te doen. Ik ga er morgen naar kijken :)
-
Dag Bas,
Ik heb je filmpje meerder malen bekeken en het is me gelukt (y). Kan de schets uploaden naar de arduino.
Maar nu ..... de aansluitingen (pin-nummers) op de arduino of hoe de L298N aan te sluiten. Of kan ik nog instellingen veranderen??
Schema of zoiets ??????
In ieder geval al hartelijk bedankt hiervoor. Ben denk ik al een stuk op weg. Nu de rest nog.
mvg
Kees
-
const int pinA = 2 ;
const int pinB = 3 ;
const int Fmin = 50 ;
const int Fmax = 100 ;
const int CS = A0 ;
const int potPin = A1 ;
const int acceleration = 500 ;
const int potMiddle = 512 ;
const int deadRange = 20 ;
Bijna alle instellingen heb ik bovenin gezet. PinA en pinB gaan naar de L298n. Hier zijn dat pin 2 en pin 3 maar je kan alle pinnen daarvoor gebruiken. Zolang de nummers maar kloppen met de fysieke pinnen. Ik zou pin 0 en 1 niet gebruiken omdat we nu nog tekst naar de monitor kan sturen. Kan handig zijn om evt te debuggen.
(https://images.beneluxspoor.net/bnls_2025/afbeelding-688a7ae2b99dd.png) (https://images.beneluxspoor.net/bnls_2025/afbeelding-688a7ae2b99dd.png)
-
Helaas Bas.
Ik krijg wel een puls op de rail waar de trein langzaam op rijd. Maar GEEN reactie op de potmeter.
Zit er iets fout in de Schets? Is wel goed te laden en ziet er uit zoals op je filmpje.
Ik heb A0 aan massa gehangen. ik heb nog geen weerstand dus het leek mij het beste om deze aan massa te hangen. het is maar een test.
Heb je een oplossing voor het probleem?
kees
-
En... hoe zit het met voor en achteruit??
-
Ik heb A0 aan massa gehangen
Dat is goed, anders zou je uno denken dat er korsluiting is.
We kunnen data naar de computer sturen en dan kunnen we zien wat er mis is. Probeer deze sketch
#include "weistra.h"
const int pinA = 2 ;
const int pinB = 3 ;
const int Fmin = 50 ;
const int Fmax = 100 ;
const int CS = A0 ;
const int potPin = A1 ;
const int acceleration = 50 ;
const int potMiddle = 512 ;
const int deadRange = 20 ;
Weistra pwm( pinA, pinB, Fmin, Fmax ) ;
void setup()
{
pinMode( potPin, INPUT ) ;
pwm.begin() ;
uint8_t currentLimit = 169 ;
/*currentLimit = Imax * Rshunt / 0.00488 -> 2.5A x 0.33R (3x 1R parallel) / 0.00488 = 169 */
pwm.setCurrentSense( CS, currentLimit ) ;
Serial.begin( 115200 ) ;
}
char buf[50] ;
void loop()
{
static uint32_t lastTime = 0 ;
if( millis() - lastTime >= acceleration ) // run every interval time
{ lastTime = millis() ;
static int8_t throttle = 0 ;
int8_t setPoint = 0 ;
int sample = analogRead( potPin ) ;
if( sample <= potMiddle - deadRange ) setPoint = map( sample, 0, potMiddle - deadRange , -100, 0 ) ; // scale [0.. middle -20] to [-100..0]
else if( sample >= potMiddle + deadRange ) setPoint = map( sample, potMiddle + deadRange , 1023, 0, 100 ) ; // scale [middle + 20 .. 1023] to [0..100]
else setPoint = 0 ; // middle 40 adc steps = dead range -> speed 0
if( throttle < setPoint ) throttle ++ ;
if( throttle > setPoint ) throttle -- ;
pwm.setSpeed( throttle ) ;
sprintf( buf, "Throttle: %d\tSample: %d\tSetPoint: %d", throttle, sample, setPoint ) ;
Serial.println( buf ) ;
}
pwm.update() ; // also handles short circuit.
}
Je kan in weistra.cpp ook nog wat code toevoegen om dingen te zien, zoals kortsluiting of stroom verbruik.
(https://images.beneluxspoor.net/bnls_2025/afbeelding-688d28086b71a.png) (https://images.beneluxspoor.net/bnls_2025/afbeelding-688d28086b71a.png)
Na het uploaden, klik je rechtsboven in de IDE op dat vergroot glas, hotkey is Ctrl Shift M en dan moet je baudrate op 115200 zetten. Dan moet je dit gaan zien.
Je kan de ADC waarde zien, de setpoint in % en de huidige snelheid/throttle.
(https://images.beneluxspoor.net/bnls_2025/afbeelding-688d28854d106.png) (https://images.beneluxspoor.net/bnls_2025/afbeelding-688d28854d106.png).
Ik had de acceleration op 500 gezet, maar met 2 updates per seconde, duurt het nogal lang, dus die heb ik aangepast naar 50. Dat moet je maar in de praktijk even aanzien wat jij fijn vindt.
Bas
-
Nog je vraag over achteruit voorruit.
Potmeter links = achteruit
potmeter rechts = voorruit.
Als ze contra zijn, kan je de 5V en GND omdraaien.
In het midden zit een 'dood' gebied waarin de snelheid 0 is. Dat zorgt er voor je makkelijk je trein kan stil zetten. Daarom kon ik niet zomaar de ADC waarde 0 <> 1023 in 1x ommappen naar -100 <> 100
(https://images.beneluxspoor.net/bnls_2025/afbeelding-688d2b8091c67.png) (https://images.beneluxspoor.net/bnls_2025/afbeelding-688d2b8091c67.png)
Nu je dit plaatje gezien, snap je wellicht deze code beter:
De If else statements stellen vast in welk gebied de potmeter staat, Links, rechts of midden. En aan de hand daarvan kies ik de snelheid waar ik de ADC dan netjes omschaal naar een setpoint.
Die functie map() die schaalt een bepaald bereik lineair om naar een ander bereik. Rete handig.
if( sample <= potMiddle - deadRange ) setPoint = map( sample, 0, potMiddle - deadRange , -100, 0 ) ; // scale [0.. middle -20] to [-100..0]
else if( sample >= potMiddle + deadRange ) setPoint = map( sample, potMiddle + deadRange , 1023, 0, 100 ) ; // scale [middle + 20 .. 1023] to [0..100]
else setPoint = 0 ; // middle 40 adc steps = dead range -> speed
https://docs.arduino.cc/language-reference/en/functions/math/map/ (https://docs.arduino.cc/language-reference/en/functions/math/map/)
-
Hoi Bas,
Bedankt voor de reactie. Ik heb dit weekend even weinig tijd.. Zal maandag avond het een een ander proberen.
Kijken of ik wat verder kom.
Dan reageer ik weer wel.
-
Bas,
Om te beginnen krijg ik deze foutmelding.
Weistra_van_benweluxspoor:53: error: expected '}' at end of input
pwm.update() ; // also handles short circuit.
Programmeren is niet mijn ding.
-
Hierboven betreft de schets die je stuurde.
-
Ik denk dat je onderste accolade vergeten bent mee te kopieren