Realtime movement of a stepper like a Blender 3d animation

332 views
Skip to first unread message

Mathias Lillich

unread,
Feb 22, 2013, 5:24:57 PM2/22/13
to accels...@googlegroups.com
Hello everybody,
 
I try to make a stepper move in realtime like a animated cube in blender 3d. Blender uses python. I have to say that I have no idea of programming or coding anyway. The codes I made are done with help of other forums. I use a big easy driver. Serial data is sent 25 times a second (like 25 frames). The goal is to send the rotation of the cube to the arduino. The arduino should calculate the steps to move. So he should subtract the old position from the new one and move these steps. By now I have these codes. They only work with the "runToNewPosition"-method. No other method like moveTo or anything else works. And at least, the runToNewPosition-method did not work correctly.
 
For example:
 
Frame 1: 200
Frame 2: 600
Frame 3: 400
 
With my codes, the stepper runs 1 revolution forward, then 3 revolutions forward and another 2 revolutions forward. But it should turn 1 revolution forward, 2 forward and 1 backward. I think the error is how the data is sent...
 
Blender(Python)Code:
 
import bpy
import math
import struct
from math import degrees
import serial
ser = serial.Serial('COM5',115200,timeout=1)
def my_handler(scene):
    eulx = bpy.data.objects['Cube'].rotation_euler
    x = degrees(eulx.y)
    xa = int(x)
    xb = xa.to_bytes(2,'big',signed=True)
    ser.write(xb)
bpy.app.handlers.frame_change_post.append(my_handler)//the handler runs every frame
 
Arduino code:
 
#include <AccelStepper.h>
int motorSpeed = 3000;
int motorAccel = 2000;
int motorDirPin = 9;
int motorStepPin = 8;
int num;

AccelStepper stepper(1, motorStepPin, motorDirPin);
void setup(){
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);
  digitalWrite(7, LOW);
  stepper.setMaxSpeed(motorSpeed);
  stepper.setSpeed(motorSpeed);
  stepper.setAcceleration(motorAccel);
  Serial.begin(115200);
  stepper.moveTo(0);
}
int numbuffer = 0;
void loop()
{
  int bytesToRead = 2;
  while(Serial.available() > 0 && bytesToRead > 0) {
    int serialByte = Serial.read();
    numbuffer += serialByte << ((bytesToRead - 1) * 8);
    bytesToRead = bytesToRead - 1;
  }
  num = numbuffer;
  stepper.runToNewPosition(numbuffer);
  delay(40);
}
 
Has anyone an idea how to fix it? Or maybe another solution that works? But as I said, I have absolutely no plan of coding...
 
Thank you very much
Mat
 
 

Sandy Noble

unread,
Feb 22, 2013, 5:51:19 PM2/22/13
to accels...@googlegroups.com
Hi there, I think your comms might be ok, but your issue is that numbuffer is never reset - it is keeping a total of all the numbers sent to it rather than counting up from 0 each time.  if you put a line like:

numbuffer = 0; 

after your delay, then you might get it running.

You're also not using the variable "num" anywhere - that won't make any difference, but just so it doesn't throw you off the scent you might want to take it out!

sandy noble



 
 

--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Sandy Noble

Mathias Lillich

unread,
Feb 23, 2013, 3:04:52 PM2/23/13
to accels...@googlegroups.com
Hello and thank you very much for answering!

At the moment I'm not able to test your suggestion, I can try it on monday. But I think that's not the solution, because when numbuffer is not reseted in the code, the movement in my Exempel above would be: 1 revolution forward, then 4 revolutions forward and then 6 revolutions forward.

Also other methods like "moveTo" for example would work. By now only the "runToNewPosition" method works.

But as I said, I'm no programmer and I will definitely give your tip a try!!!

You are also right with "num".... I never used it and I will remove it!

Thank you very very much for trying to help me!!!
Mat

Sandy Noble

unread,
Feb 23, 2013, 6:05:47 PM2/23/13
to accels...@googlegroups.com
Hi Mat, runToNewPosition uses absolute positioning rather than relative, so it will turn from 0 (start position), to position 200 (one full revolution), to position 600 (two more full revolutions) to position 400 (one revolution backwards).

At the moment your code is moving to position 200 (one full rev), then to 800 (200+600 - three more revs) and then to 1200 (200+600+400 - two more revs), which is what you've described seeing.

runToNewPosition() works on it's own because it blocks other processes - it doesn't need to be in a loop to run.  Something like moveTo() or move() only sets a target rather than doing any actual moving.  After setting a target, you need to hit run() lots of times to actually run the motor itself.

So instead of stepper.runToNewPosition(numbuffer) you might have

stepper.moveTo(numbuffer);             // set the target
while (stepper.distanceToGo() != 0)  // and while there is still some distance to get there:
{
     stepper.run();  // run the motor
}


It's worth using that pattern if you want to do something else while the motor is moving - send signals, or get more information or something like that.  Sometimes nice to have a faster response since it doesn't necessarily need to wait until the motor has finished before responding to more commands.

good luck :)

sandy noble



--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.





--
Sandy Noble

Mathias Lillich

unread,
Feb 25, 2013, 1:02:06 AM2/25/13
to accels...@googlegroups.com
Hi Sandy,
 
I´ve tried out all you suggestions and you are absolutely right! Thank you very very much!!! I used the moveTo-method simply the wrong way. I always did:
 
stepper.moveTo(numbuffer);
stepper.run();
 
But with your method it works.
 
Now I have some other problems which I have to care for: because I clear the numbuffer, the stepper always goes to 0 when I stop the animation and the second problem is the timing (delay). Long ways need more time than shorter ones :-) In short periods the arduino loop is faster than python and resets to 0 and so on......
 
But again: Thank you very much! I try to get it done and let you know.
 
Mat
Reply all
Reply to author
Forward
0 new messages