Make an object rotate once a minute

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
Devavictrix
Posts: 8
Joined: Mon Apr 17, 2017 2:35 pm

Make an object rotate once a minute

Post by Devavictrix »

I am trying to make a gear chain that operates like a watch. I have built my gears and found some code on youtube to get them to rotate and it all works well, except the timing.

I don't know python (or any other language other than English!) but can usually work how to edit existing code. My problem is that I don't seem to be able to figure out what the code thinks is a second, or minute...

Here is my code.
Ultimately, I want CycloideGear005 and CycloideGear006 to rotate once every 60s and CycloideGear001 and CycloideGear002 to rotate once every 3600s. The multiples of i in my code are the gear ratios respective to CycloideGear.

I hope someone can help!
Thank you

Code: Select all

from PySide import QtCore

i = 0
def update():
	global i
	App.getDocument("new_watch").CycloideGear.Placement=App.Placement(App.Vector(0,0,0), App.Rotation(App.Vector(0,0,1),(i)+1.9), App.Vector(0,0,0))
	App.getDocument("new_watch").CycloideGear001.Placement=App.Placement(App.Vector(14.04,0,0), App.Rotation(App.Vector(0,0,1),(-i*8)), App.Vector(0,0,0))
	App.getDocument("new_watch").CycloideGear002.Placement=App.Placement(App.Vector(14.04,0,1.1), App.Rotation(App.Vector(0,0,1),(-i*8)), App.Vector(0,0,0))
	App.getDocument("new_watch").CycloideGear003.Placement=App.Placement(App.Vector(25.29,0,1.1), App.Rotation(App.Vector(0,0,1),(i*64)+18), App.Vector(0,0,0))
	App.getDocument("new_watch").CycloideGear004.Placement=App.Placement(App.Vector(25.29,0,0), App.Rotation(App.Vector(0,0,1),(i*64)+18), App.Vector(0,0,0))
	App.getDocument("new_watch").CycloideGear005.Placement=App.Placement(App.Vector(34.34,0,0), App.Rotation(App.Vector(0,0,1),(-i*480)-8.6), App.Vector(0,0,0))
	App.getDocument("new_watch").CycloideGear006.Placement=App.Placement(App.Vector(34.34,0,1.1), App.Rotation(App.Vector(0,0,1),(-i*480)-8.6), App.Vector(0,0,0))
	App.getDocument("new_watch").CycloideGear007.Placement=App.Placement(App.Vector(40.94,0,1.1), App.Rotation(App.Vector(0,0,1),(i*4800)+18.5), App.Vector(0,0,0))
	i += 1

timer = QtCore.QTimer()
timer.timeout.connect( update )
timer.start()
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: Make an object rotate once a minute

Post by triplus »

Hi @Devavictrix.

Please attach the corresponding .FCStd file.
Devavictrix
Posts: 8
Joined: Mon Apr 17, 2017 2:35 pm

Re: Make an object rotate once a minute

Post by Devavictrix »

Thank you for replying. I have just started to upload it to onedrive but realised its 56mb! Is this kinda file size normal? I just have 8 tiny gears (1-25mm diameters) and that short bit of code!

Edit: Turns out set something setting that made it huge! This file is 1.8mb

https://1drv.ms/u/s!AgxozSwFAqyOpbdrf3SvkjLrxdctvg
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: Make an object rotate once a minute

Post by triplus »

This is the line that will give you control over the rotation speed:

Code: Select all

timer.start()
You can at any time stop the rotation:

Code: Select all

timer.stop()
Or set the time interval:

Code: Select all

timer.start(1000)
Value 1000 represents 1s/1000ms.
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: Make an object rotate once a minute

Post by triplus »

In addition you will likely want to replace:

Code: Select all

App.getDocument("new_watch").
With:

Code: Select all

App.ActiveDocument.
As after the name of the .FCStd file won't need to be "new_watch" anymore. And look in the code snippet for:

Code: Select all

   i += 1
Try changing the value to for example:

Code: Select all

   i += 0.01
With a bit of math this likely is the control you need. To get a gear to turn once in 60s and for the rotation animation on the screen to be smooth.
Devavictrix
Posts: 8
Joined: Mon Apr 17, 2017 2:35 pm

Re: Make an object rotate once a minute

Post by Devavictrix »

Thank you.
I realised that the "new watch" bit was an error after I changed the name of my file to gear train.

Code: Select all

timer.start()
seems to decide the interval, so when I set it to 1000 it updates the gears each second. I will leave it either blank or "1" so that the animation is smooth.

I have been playing with the "i += 1" quite a bit I can't figure the maths.
If I concentrate on

Code: Select all

App.getDocument("new_watch").CycloideGear.Placement=App.Placement(App.Vector(0,0,0), App.Rotation(App.Vector(0,0,1),(i)+1.9), App.Vector(0,0,0))
... I would expect it rotate once (given z is set at 1...App.Vector(0,0,1), and i has no multiples. The 1.9 sets the start position so that the teeth line up with the next pinion) but it goes round in a few seconds. Hence why I don't know what i actually is when it's 1! 1 something, but certainly not 1s.

I'll keep plugging away at it!

Thank you for your replies
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: Make an object rotate once a minute

Post by triplus »

I don't have more time today to go into details and precise calculations. As for a quick guess. Set timer interval is related to everything else. And having it set at 1ms is overdoing it and stressing FreeCAD out for no benefit.

Code: Select all

timer.start(1000/60)
This should roughly produce 60 update intervals each second (60FPS). And setting:

Code: Select all

    i += 0.1
Translates to (very) roughly one turn of CycloideGear each minute. For anything else (accuracy related) more time and calculations would need to be invested.
Devavictrix
Posts: 8
Joined: Mon Apr 17, 2017 2:35 pm

Re: Make an object rotate once a minute

Post by Devavictrix »

ahhh, thank you. Setting i to 0.1 does indeed seem to make the first wheel rotate at 1rpm. I divided 0.1 by 480 (= 0.000208333333) and this seems to make the fourth wheel rotate at 1rpm. tbh, I tried to time it with my phone and I got one revolution at 57s but I suppose that'll do for now... it could be my timing of course!

Thank you for you help!
triplus
Veteran
Posts: 9471
Joined: Mon Dec 12, 2011 4:45 pm

Re: Make an object rotate once a minute

Post by triplus »

Devavictrix wrote:Thank you for you help!
You're welcome.

P.S. And i did a quick test. When QTimer interval isn't set the rotation speed will be hardware dependant. More CPU power equals faster rotation. Therefore it is important to set reasonable time interval (based on the complexity of model) to get consistent results on different hardware. Note that if model is too complex there is no guarantee hardware will be able to produce 60 intervals each seconds. And that will result in slower rotation of the gear than expected.
Devavictrix
Posts: 8
Joined: Mon Apr 17, 2017 2:35 pm

Re: Make an object rotate once a minute

Post by Devavictrix »

I had a good read of the documentation to PySide and it said the same thing... that different computers will provide different results.

It also helped me understand the code better. It said pretty much what you did...

timer.start() is the interval that it updates (in milliseconds) and "i" is the number of degrees it updates upon each interval. So for a ticking second hand on a watch you'd set timer.start() to timer.start(1000) and i+=6 (6 degrees each second, 360/60=6).

In my case, everything was geared from the big gear. The gear I wanted to turn at 1rpm was rotating 480 times for 1 revolution of the big gear so I divided all the ratios by 480. I took you advise on updating 60 times a second (almost matching my screen refresh rate) so used timer.start(1000/60) and i+=6/60 (This didnt actually work... I had to use i+=0.1). I later discovered that if you are multiplying "i" by a fraction you need to enter the fraction with .0 after each number.

Thank you for all the help!
Post Reply