klein is fijn
Moderator
Even wat inleiding: Voor school ben ik bezig met mijn stage, een CD opstelling bouwen in het laserlab van de VU. In deze opstelling komt ook een monochromator voor, dat is een apparaat die licht van maar 1 golflengte naar keuze doorlaat. Deze monochromator moet worden aangestuurd met de computer, hiervoor heb ik een stappen motor eraan laten maken.
Het resterende probleem was dus de aansturing van de stappenmotor. Gezien ik een opleiding Analytische Chemie doe zit dit totaal niet in mijn lespakket.
Ik had hiervoor een stukje code gevonden op het internet, geschreven in Bascom AVR, afkomstig van dit project.
Nu weten meerdere mensen hier dat ik niets van uC's afweet, maar ik heb toch eens wat zitten rommelen in het programma.
Ten eerste wilde ik de snelheid regelbaar hebben, ik wilde een ready terug hebben als het ding klaar is met draaien, en ik wilde een hardware busy LEDje hebben. Het was de bedoelding dat het geheel gaat draaien in een ATtiny2313.
Na wat googlen en wijzigen ben ik hier op uitgekomen:
$crystal = 4000000
$baud = 9600
Dim Wa As String * 2 , Wb As Byte
Dim Stap As Integer , A As Integer , Dir As String * 3 , Value As String * 8
Dim Step1 As Byte , Step2 As Byte , Step3 As Byte , Step4 As Byte
Config Portb = Output
Config Portd = Input
Print "Serial Port Stepper Motor Driver"
Print "input mmdsxxxxx in which mm=m0/m1, d=l/r, s=1-9, xxxxx=1-32000"
Lus:
Input "Give input: " , Value
Dir = Left(value , 3)
Wa = Mid(value , 4 , 1)
Wb = Val(wa)
Value = Mid(value , 5 , 5)
Stap = Val(value)
If Dir = "m0l" Then
Step1 = 48
Step2 = 96
Step3 = 192
Step4 = 144
Gosub Steps
Print "ready"
End If
If Dir = "m0r" Then
Step1 = 144
Step2 = 192
Step3 = 96
Step4 = 48
Gosub Steps
Print "ready"
End If
If Dir = "m1l" Then
Step1 = 3
Step2 = 6
Step3 = 12
Step4 = 9
Gosub Steps
Print "ready"
End If
If Dir = "m1r" Then
Step1 = 9
Step2 = 12
Step3 = 6
Step4 = 3
Gosub Steps
Print "ready"
End If
Goto Lus
Steps:
Portd.2 = 1
For A = 1 To Stap
Portb = Step1
Waitms Wb
Portb = Step2
Waitms Wb
Portb = Step3
Waitms Wb
Portb = Step4
Waitms Wb
Portb = 0
Next A
Portd.2 = 0
ReturnNu ziet het er in de simulatie van Bascom AVR wel allemaal werkend uit, maar kan iemand mij uitsluitsel geven of dit werkt, of anders tips hoe dit beter kan?
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Ik stel me vragen bij je stappen. Activeer jij telkens 2 wikkelingen van je motor(s)? Dat is toch nergens voor nodig? Of miskijk ik me op je code (waar ik geenszins vertrouwd mee ben)?
klein is fijn
Moderator
Er worden inderdaad steeds twee wikkelingen tegelijk geactiveerd.
Zoveel ervaring heb ik ook niet met stappenmotoren, dus ik had maar even aangenomen dat die hele sub voor 1 stap goed was en heb de waardes van portb overgenomen.
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Als het een unipolaire motor (4 wikkelingen, 6 aansluitdraden) betreft, kan je het zo doen:
Wikkeling 1: A en B
Wikkeling 2: C en D
A - C - B - D - A - C - ... (of andersom)
of
A - AC - C - CB - B - BD - D - DA - A - AC ... (of andersom)
In het 2e geval draait de motor trager, maar zijn de stappen half zo groot.
[Bericht gewijzigd door pros op ]
klein is fijn
Moderator
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
klein is fijn
Moderator
Ah. Nu snap ik waarom er "For A = 1 To Stap Step 4" in de orginele code staat, hij loopt met stappen van 4 lang door de waardes van A..
* klein is fijn opent prullebak en schuift code erin.
Ik heb dus iets nodig waarmee je 1 stap per keer kan nemen, niet 4 tegelijk.
(Z)weetvoetje
Hogepriester in het genootschap der mexicaanse hond. // // Aan 2% van de mensen is 50% van het bezit ; 1% van het bezit is aan 50% van de mensen.
Waarom niet met een paar losse chippies? Da's ook heel gemakkelijk hoor. Neem zo'n up-downcount IC'tje met 4 bits. (in 2 bits heb je ze niet) en dan ff met EN/xor poortjes en invertortjes klooien. Dan heb je t ook.
In 3 IC's heb je de complete sturing, een 4029, een 4*XOR IC, en een uln2003 (500mA invertors, voor direct op de motor)
klein is fijn
Moderator
Das allemaal geen probleem, maar dat hangt zo rot aan de seriele poort. Het is de bedoeling dat het ding straks met staptjes van 1nm een heel spectrum gaat doorlopen. Aan de andere kant hangt de detector ook aan de computer en van die twee wordt een leuk grafiekje in elkaar gezet.
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Ik doe meestal zoiets:
#define RECHTS 1
#define LINKS 2
unsigned char motor1[4] = { 48, 96, 192, 144 };
char step1 = 0;
void stappen_maar(unsigned char richting, unsigned int aantal)
{
while (aantal > 0) {
if (richting == RECHTS) {
step1++;
} else {
step1--;
}
step1 &= 3; // we gebruiken van "step1" enkel bits 0 en 1
PORTB = motor1[step1];
aantal--;
}
}
// code...
stappen_maar(RECHTS, 12);
// enz...
Voor een 2e motor maak je een 2e array (motor2) aan, en gebruik je uiteraard een 2e variabele (step2) om de motorstand bij te houden. Wil je met halve stappen werken, dat heb je per motor een array van 8 stappen nodig, en doe je "step1 &= 7".
Het bovenstaande zal wel om te zetten zijn naar bascom, hoop ik...
Als het principe van pros inderdaad opgaat voor jouw motor, zou ik het zo doen. Heb je geen datasheet van die stepper? Als het bekend is hoe je het spul aan moet sturen, is het helemaal appeltje-eitje. Ik kan je met bascom niet helpen. Ben meer van de assembly...
klein is fijn
Moderator
Ik ben wat in elkaar aan het prutsen in bascom, maar ik kom erachter dat het behoorlijk behelpen is.
De plek bijhouden waar de stepper staat is geen probleem, maar die plek omzetten naar wat anders is wat lastig.
Ook schijn ik niet in 1 commando 8 dingen in een array te kunnen proppen, daar zijn weer 8 regels voor nodig..
Het probleem waar ik nu ook weer mee zit is het feit dat er twee stappenmotoren op 1 poort hangen en ik toch wel graag nu meteen 1/2 step wil gaan werken. Er moet dus spanning op blijven staan, maar hoe verander ik de eerste of laatste 4 bits van een poort zonder de andere te veranderen?
* klein is fijn vraagt zich even voorzichtig af of hier geen betere taal voor is dan bascom.
Dat voorbeeldje stond toevallig in bascom, maar volgens mij zijn er veel handigere manier om dit te schrijven.
Tsja... ik blijf erbij dat je uC's gewoon in assembly programmeert. Punt. Maar goed...
In tegenstelling tot bijvoorbeeld een 8051, kun je op AVRs redelijk veilig read-modify-write doen. Ofwel: je doet een read van die port (niet, niet van PINx maar van PORTx), AND het resultaat met een bitmask met 1-en op de plaatsen van 'de andere motor' (alles van 'jouw' motor is nu 0) en ORed daar de nieuwe waarde (van 4 bits) overheen (yep, even 4 bits shiften voor de hoogste 4...). Vervolgens schrijf je het spul weer. Dat moet ook in basic nog wel lukken.
Alternatief is bitjes stuk voor stuk setten (weet niet op die motor dat leuk vindt; aan de andere kant... als je dat @10MHz doet en bascom compileert je code wat handig, gaat het waarschijnliujk zo snel dat die motor het niet eens door heeft. Geen idee hoe je in bascom 1 pin set / cleared.
De 'netste' en meest 'hufter-proof' manier is een shadow register bijhouden: je hebt een byte waar de status van je output pins in staan. Die kun je als boven omschreven manipuleren en schrijf je dan naar je poort. Voordeel van read-modify-write is dat er niet per ongeluk bitjes 'om kunnen vallen'. Gezien de opbouw van ports op een 8051 ontkom je niet aan deze manier, tenzij je bit-voor-bit zet.
(Z)weetvoetje
Hogepriester in het genootschap der mexicaanse hond. // // Aan 2% van de mensen is 50% van het bezit ; 1% van het bezit is aan 50% van de mensen.
gewoon in assembly pin voor pin programmeren. Dat gaat heel eenvoudig. Je kan binnen 10 cycles alle pinnen goed gezet hebben. Da's ruim snel genoeg.
Hoeveel motoren moet je nou eigenlijk aansturen, en hoeveel andere dingen moet de microcontroller eigenlijk bijhouden?
Roland van Leusden
It's the rule that you live by and die for It's the one thing you can't deny Even though you don't know what the price is. It is justified.
Ook schijn ik niet in 1 commando 8 dingen in een array te kunnen proppen, daar zijn weer 8 regels voor nodig..
statement data gebruiken ...
http://web.inter.nl.net/users/cpotma/bascom%20and%20avr/arrays%20and%2…
klein is fijn
Moderator
Ik ben gisteravond wat aan het prutsen geweest en ik heb wat leuks (hoop ik) in elkaar gedraaid:
$crystal = 4000000
$baud = 9600
Dim A As Integer
Dim Dir As String * 3 , Value As String * 8 , Stap As Integer
Dim Wa As String * 2 , Wb As Byte , Stepdirection As Integer
Dim Stepm1 As Byte , Stepm2 As Byte
Dim Posm1 As Integer , Posm2 As Integer
Dim Stepsm1(8) As Byte , Stepsm2(8) As Byte
Dim Portbm1 As Byte , Portbm2 As Byte
Config Portb = Output
Config Portd = Input
Stepsm1(1) = 8
Stepsm1(2) = 10
Stepsm1(3) = 2
Stepsm1(4) = 6
Stepsm1(5) = 4
Stepsm1(6) = 5
Stepsm1(7) = 1
Stepsm1(8) = 9
Stepsm2(1) = 128
Stepsm2(2) = 160
Stepsm2(3) = 32
Stepsm2(4) = 96
Stepsm2(5) = 64
Stepsm2(6) = 80
Stepsm2(7) = 16
Stepsm2(8) = 144
Portbm1 = 8
Portbm2 = 128
Portb = 136
Print "testprogram"
Print "input mmdsxxxxx in which mm=m0/m1, d=l/r, s=1-9, xxxxx=1-32000"
Lus:
Input "Give input: " , Value
Dir = Left(value , 3)
Wa = Mid(value , 4 , 1)
Wb = Val(wa)
Value = Mid(value , 5 , 5)
Stap = Val(value)
If Dir = "m1l" Then
Stepdirection = -32
Gosub Subm1
End If
If Dir = "m1r" Then
Stepdirection = 32
Gosub Subm1
End If
If Dir = "m2l" Then
Stepdirection = -32
Gosub Subm2
End If
If Dir = "m2r" Then
Stepdirection = 32
Gosub Subm2
End If
Goto Lus
Subm1:
Portd.4 = 1
For A = 1 To Stap
Stepm1 = Stepm1 + Stepdirection
Posm1 = Stepm1 / 32
Posm1 = Posm1 + 1
Portbm1 = Stepsm1(posm1)
Portb = Portbm1 + Portbm2
Waitms Wb
Next A
Portd.4 = 0
Print "ready"
Return
Subm2:
Portd.5 = 1
For A = 1 To Stap
Stepm2 = Stepm2 + Stepdirection
Posm2 = Stepm2 / 32
Posm2 = Posm2 + 1
Portbm2 = Stepsm2(posm2)
Portb = Portbm1 + Portbm2
Waitms Wb
Next A
Portd.5 = 0
Print "ready"
ReturnPortbm1 en Portbm2 zijn de schaduwbytes die de poortstand bijhouden van beide steppers.
Aan Portd.4 & Portd.5 hangen twee busy LED's.
In de simulatie werkt het allemaal prima, maar ik toch nog wat vragen.
Hoe kan je berekenen hoelang 1 keer zo'n sub doorlopen kost? Stel het kost 20ms om die sub te doorlopen dan heeft die 3ms wachttijd ook geen zin.
De Config van Portd staat op Input, maar Portd.4 & Portd.5 worden gebruikt als output. Nu werkt dat allemaal wel leuk in de simulatie, maar moet ik per se als &B00001100 configgen als ik wil dat het ook in het echt werkt?
Ik heb die array's op een andere manier proberen te vullen, maar dit blijkt minder ruimte in te nemen dan een stel commando's.
Wel een leuk feit, deze code is even groot als het voorbeeld waar ik mee begon. 
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Hoe kan je berekenen hoelang 1 keer zo'n sub doorlopen kost? Stel het kost 20ms om die sub te doorlopen dan heeft die 3ms wachttijd ook geen zin.
Berekenen? Bij een assembler-programma is dat nog te doen, daar weet je precies welke instructies er gebruikt worden. Bij c heb je er het raden naar. Maar je kan de compiler wel opdragen, de assembler-source (die normaal tussendoor aangemaakt en terug verwijderd wordt) te laten staan, en aan de hand daarvan je berekeningen te maken. Hoe dat met basic zit? 'k Zou 't begot niet weten...
Anderzijds denk ik dat je één enkele doorlooptijd van je subroutines eerder in µS moet uitdrukken.
Toch nog een (misschien onterechte) opmerking:
For A = 1 To Stap
Moet dat niet zo:
For A = 0 To Stap
klein is fijn
Moderator
Op 19 februari 2007 21:00:59 schreef pros:
Berekenen? Bij een assembler-programma is dat nog te doen, daar weet je precies welke instructies er gebruikt worden. Bij c heb je er het raden naar. Maar je kan de compiler wel opdragen, de assembler-source (die normaal tussendoor aangemaakt en terug verwijderd wordt) te laten staan, en aan de hand daarvan je berekeningen te maken. Hoe dat met basic zit? 'k Zou 't begot niet weten...
Anderzijds denk ik dat je één enkele doorlooptijd van je subroutines eerder in µS moet uitdrukken.
Oke, dat zit dus wel goed.
Toch nog een (misschien onterechte) opmerking:
For A = 1 To StapMoet dat niet zo:
For A = 0 To Stap
Nee, ik heb het dubbel gecheckt en het moet echt 1 zijn. Stel Stap is ook 1, dan doorloopt ie van 1 tot en met 1, 1x dus.
klein is fijn
Moderator
* klein is fijn schopt dit topic nog even omhoog omdat hij met iets zit waar hij niet uit komt.
Ik verwijs naar deze sub voor het stappen:
Subm1:
Portd.4 = 1
For A = 1 To Stap
Stepm1 = Stepm1 + Stepdirection
Posm1 = Stepm1 / 32
Posm1 = Posm1 + 1
Portbm1 = Stepsm1(posm1)
Portb = Portbm1 + Portbm2
Waitms Wb
Next A
Portd.4 = 0
Print "ready"
ReturnNu gaat dat prima, alleen het LEDje dat aan Portd.4 hangt gaat amper aan. Ik zie een heel zwak lichtpuntje.
Dus ik had even een knipperlicht programma erin geschoven om het te testen en de LED brand gewoon normaal.
Waarom brandt mijn LED zo zwak als die stepper code draai?
Ik neem aan dat je die LED zo aangesloten hebt dat het ding met een '1' brandt (ik zou het zelf andersom doen omdat die port beter sinkt dan sourced en ik zo geen zooi erachter nodig heb). Als dat niet zo is, zou je meer over de routine die dit stuk code aanrept moeten weten om er wat zinnigs over te zeggen.
Geen idee hoe snel die routine is. Ik weet wel dat de LED intensiteit zoals je die waarneemt niet lineair verloopt met de duty-cycle.
Zou het kunnen dat je voeding bij elke stap wat instort waardoor de stroom door de LED een stuk lager wordt dan dat je denkt?
klein is fijn
Moderator
Het geheel is de code hierboven die ik al eerder had neergezet.
De sub wordt 1 keer aangeroepen waarna ie "stap" aantal keer in die sub rondrent. Het LEDje gaat dus maar 1 keer aan en een keer uit, daartussen blijft het constant branden. De voeding heb ik ook al gemeten, die blijft gewoon 5V ten alle tijden.
De poort laten sinken is natuurlijk een idee en misschien wel wat netter, maar toch vind ik het vreemd dat sourcen niet werkt met deze code.
Beter laat dan nooit hier og wat info
http://gathering.tweakers.net/forum/list_messages/802060#sluitaan
klein is fijn
Moderator
Das inderdaad wat laat, en over een totaal ander iets. Wat jij post dat gaat over stappenmotoren aansturen via de parallele poort en Visual Basic, ik ben stappenmotoren aan het aansturen via een microcontroller.
Projectjes is overgens bijna af, ben momenteel een behuizing aan het ontwerpen / maken. Print is al bijna af, moet alleen nog in elkaar gesoldeerd worden (het minste werk).