Skip to main content

Home and Move commands are not working properly

Posted in

I know there have been discussions about this in the past, but I still seem to have issues with home and move.

I am currently testing my dolly. The dolly has a 300k steps resolution over two meters. My engine is version 0.82.

My dolly is not able to use move commands with over 64k number of steps at one time. The home command doesn't bring back the motor to the correct place if the number of steps (either because of multiple home commands or after a completed time lapse series) was over 64k.

This is a bit strange since a quick look at the code reveals that a long variable is used. That should be large enough I guess.

Maybe Chris can help me out here before I spend a lot of time browsing through the TLE code? Is this by design? Or is this a bug? Is Slim communicating correctly with the TLE (using the correct sizing)?

Andre, I found the problem

Andre,

I found the problem with home --

See, inside the motor home function:

   // we have to move in a direction opposite
   // that of which we have gone away from home
   // (i.e. undo our steps)
   
 if( *home_pos < 0 ) {
   set_motor_dir(motor, 1);
 }
 else {
   set_motor_dir(motor, 0);
 }
 
 motor_pulse_steps_linear( motor, (unsigned long) abs(*home_pos) );

  // set motor back to whatever direction it was going
 set_motor_dir( motor, was_dir );
 
  // reset relationship to home
 *home_pos = 0;

That call to abs() is the issue. abs() returns a (signed!) int. In fact, abs() is just bad - I thought I had eliminated all calls to it, but apparently not!

You can replace that code with the code from the nanomoco branch, where I've already fixed it:

(other code in nanomoco may still be considered 'experimental', but it has continuous motion support too =)

 byte dir = 0;
 if( home_pos < 0 ) {
   dir = 1;
     // invert value for abs steps
     // (abs() returns an int)
   home_pos *= -1;
 }

  motor_pulse_steps_async( dir, home_pos );

(note 'motor_pulse_steps_async' would need to be replaced by two calls in 0.82: motor_set_dir, and motor_pulse_steps_linear; also note that nanomoco has only one motor, so be careful to follow the way 0.82 gets direction, also note that you'll never be able to go a full unsigned long distance to home, given that home is a signed long [we should probably change this to two variables, direction from home and distance from home to overcome this])

As for the move command... It is limited to 16 bits of steps (65,535 total steps). This is due to the serial protocol (it was designed for consistency between keyframe and move actions - so you could do anything with a keyframe that you can do with move). You'll see this here inside of the serial pde:

unsigned int steps   = ( (unsigned int) input_serial_buffer[3] << 8 ) + (unsigned int) input_serial_buffer[4];

If you want to make it a long, need to follow the format used in other long values passed via the api, e.g.:

                  unsigned long ths_tm = 0;
                 
                   ths_tm  = (unsigned long) ( ( (unsigned int) input_serial_buffer[1] << 8 ) + ( (unsigned int) input_serial_buffer[2] ) ) << 16;
                   ths_tm |= (unsigned long) ( ( (unsigned int) input_serial_buffer[3] << 8 ) + ( (unsigned int) input_serial_buffer[4] ) );

!c

Hi Chris, I will give this

Hi Chris,

I will give this try. Your reply makes me even more eager to switch to the NanoMoco engine!

Yeah, it's definitely going

Yeah, it's definitely going to be a lot better, started out yesterday building a model, simple, motor control GUI to show the idea (in Qt), and ended up spending the entire day trying to work out issues in the serial communication. *sigh* So, it's not ready for prime time yet (although, I fear, the problem lies somewhere in the low-level Serial implementation - or at least how it's being used here.) - of course, it probably happens in 0.82 too, so no clue yet!

(But, it does have a proper continuous motion control and sms both using async control now, so I'm feeling better about that part.)

!c

Can you tell me more about

Can you tell me more about the serial issue? I had issues in the past when I connected my TouchShield Slide to an Adruino. I used most of the serial stuff from the engine for that. I have changes/fixed some of the code I believe at that time.

The primary issue seems to be

The primary issue seems to be that either the start sequence is received corrupted, or the entire data sequence is not received at all at certain times. I know this because the arduino side will throw an error sequence if it times out reading any byte in the start sequence.*

(The new protocol requires a start sequence that also includes an address of the device you want to talk to -- the start sequence [0,0,0,0,0,255] represents a stream of bytes that should never occur in normal protocol usage.)

(* - actually, this is specious - there is not evidence of the actual corruption of data, to be honest, it's more likely that the serial handling is "doing it wrong" somewhere.)

It will happen from time to time no matter the speed of communication (timing between requests, not bit rate - I've determined that slowing the baud down does not change the problem at all), but increases dramatically as the rate of communication requests increases. I know it's not -missing- bytes in the start sequence in the interactive mode (issueing commands by hand), b/c I never get an error sequence response. However, when slamming in requests as fast as possible through Qt, I get back error sequences - which mean either the start sequence timed out, or the data was corrupted after the start sequence. (I can verify the correct sequence.)

The new slim lists each byte sent and received, for debugging, and I see no evidence of later bytes being corrupted in interactive mode.

I've taken u2x out of the equation by forcing (modifying the HardwareSerial lib) it into both u2x and non-u2x modes, with no changes. So the problem certainly isn't there.

To be honest - I'm quite certain the issue is with my code, as I just sent thousands of characters at the same bit rate, and had it echo back - and did not get one error.

EDIT: there appear to be two problems, neither of them with the serial handling code (directly) as far as I can tell. I thought that I was able to repeat the problem using straight serial (instead of RS485) - but the fact was that only happened with the Qt library. Slim is -not- having this issue going straight over USB to TTL serial. So, there are two problems: 1 with Rs-485, and another with the Qt library, which I'm not going to worry about until I fix the RS-485 problem.

EDIT AGAIN: *sigh* I'm an idiot. I found the cause of the problem, and it's downright stupid. I can't believe I spent all day yesterday working on this and didn't even look into how I was handling the transceiver state! The problem is such: to use RS-485, you need a transceiver. Being half-duplex protocol, you have to inform the transceiver as to whether you are sending or receiving. You do this by controlling the state of the DE/RE pins (they have inverse relationship, so they are tied together). It does take a brief amount of time to flush out the last byte through the transceiver, so you have to delay a moment after sending the last byte before turning the state down... And, well, while the arduino end is waiting, the client on the other end doesn't know anything at all about the state of the RS-485 transceiver at the other end - it sends its bytes during the transition time between transmit and receive change! *face palm* At least it's a moderately easy fix =)

!c