Skip to main content

Please, I need a little modification in openmoco-slim.pl

Posted in

Hello

I have modified OM_serial_control, OM_motor_control and added 3 variables in OpenMoco_TimeLapse_engine
unsigned long pasos_a_mover = steps that I must move
byte direccion_a_mover = direcction I must move the motor
byte motor_a_mover = number of motor to move

In OM_motor_control I have modified
void motor_pulse_steps_linear( byte motor, unsigned int steps )
If motor to move is 0 or 3 I let the program to run without modifications
if motor is 1 or 2 first of all I save the content of input_serial_buffer[0] and [1], then I assing 100 to input_serial_buffer[0] and 100 to input_serial_buffer[1] after that I call serial_program_action (), then I restore the previous values of input_serial_buffer 0 and 1.

serial_program_action is modified to allow when input_serial_buffer 0 and 1 are equal to 100 to send via serial port this info:

 case 100:                
     // action data
        serial_write((byte)255);
        serial_write((byte)6);
                 
        serial_write( motor_a_mover );      // a byte
        serial_write( direccion_a_mover );  // a byte
        serial_write( pasos_a_mover );      // a unsigned long
        sent = true;
        break;

and now, my problem is that openmoco-slim do not recognice a command sent by openmoco-engine with that data inside.

Then I request you a little modification in openmoco-slim to allow it to receive that kind of message and to discard it, because this message goes to the second arduino not for the computer.

This would allow me and other people make motorized heads based on DC motors with encoders, or use existing ones jet in the market.

I ask you this because I do not program in perl.

Best Regards
Inco.

Hi Inco, The problem you are

Hi Inco,

The problem you are going to run into is that you are usurping the response code part of the protocol. Meaning, you're overloading the response byte. Not generally a safe thing to do, but I, of course, wouldn't want you to stop being able to do what you need to do =)

Here ya go, in TimeLapse.pm: (Presuming you're using 0.03 version of library)

Starting at line 1977:

                # if an unexpected value (anything but 1)
                # is received, die out of the eval,
                # setting $@
 
         if( $ret_val == 0 ) {
           die("Engine responded with error\n");
         }
         elsif( $ret_val != 1 ) {
           die("Engine responded with unknown code: $ret_val\n");
         }
 
 
                # get specified amount of data
 
         if( $len > 0 ) {
 

Should be changed as follows:

                # if an unexpected value (anything but 1)
                # is received, die out of the eval,
                # setting $@
 
         if( $ret_val == 0 ) {
           die("Engine responded with error\n");
         }
         elsif( $ret_val != 1 && $ret_val != 255 ) {
           die("Engine responded with unknown code: $ret_val\n");
         }
 
 
                # get specified amount of data
 
         if( $len > 0 ) {
 

That way it excludes your return value of 255, and doesn't attempt to process the resulting data in any way.

You should NOT, however, allow it to send a normal response after your modified response! When you say you restore input_serial_buffer, I sure hope you don't call serial_program_action or serial_program_data again - as this would result in two responses going down the serial line. With two responses on the line, the perl end will only read the first, and then the next is sitting in the buffer, and you will always be off by one response. You would have to change the perl code to then read the second response, and discard it, or operate normally with it - meaning a bit more work there =)

!c

Ok, I have tested this option

Ok, I have tested this option and there are many problems.
Now, I have my two arduinos talking over i2c, then I must make you a suggestion:
Could you change ALT_PIN from 19 to 17 and then let free the pins 18 and 19 to I2C ?

and what do you think about the next idea?

to add an array

byte motor_info[4][2] or [motor number] [internal or external] [pin_number or I2C device number]

if [ motor_info[1][1] ] == 0 -> openmoco controls the motor 1
[ motor_info[1][2] ] = pin_number of this motor

if [ motor_info[1][1] ] == 1 -> an I2C device controls the motor 1
[motor_info[1][2] ] = I2C device identification number in the I2C bus

and modify void motor_pulse_steps_linear( byte motor, unsigned long steps ) in the next way:

in line 135 of OM_Motor_Control add

if (motor_info[motor][0] == 0 ){ your code
    for( int i = 0; i < steps ; i++ ) {
       
            digitalWrite(motor_pin, HIGH);
           
            if( i < shelf_lo ) {   etc, etc.
   }

   else { // send data over I2C
          Wire.beginTransmision(motor_info[motor][2]);  // device number
          Wire.send(motor);  // send motor number
          Wire.send((  (motor_status & (B00001000 >> motor) ) != 0 )  // send direction
          Wire.send( (byte) ( steps >> 24) );
          Wire.send( (byte) ( steps >> 16) );
          Wire.send( (byte) ( steps >> 8) );
          Wire.send( (byte) ( steps ));         // sending steps
          Wire.endTransmission();
     }

    // ***************************   and now, your code again

    // update number of steps moved
    // make sure to remove the ghost steps
    // we used for backlash compensation
    //
    // we don't count steps taken during repeat cycles
   
  if( ! (action_status & B00100000) )
    motor_steps_moved[motor] += (unsigned long) ( steps - backlash_val );
 
    // update relationship to home --
    // if going in positive direction, increase distance

    // etc, etc

 

by this way you allow:
use any kind of motor (steppers or servos)
openmoco is free almost all the time to receive new commands or status requests
you could reduce "interval" between shots
let more free pins in openmoco (buttons for manual or real_time control? )

Best regards
Inco.

You're right that i2c is a

You're right that i2c is a good path to take, or even using a softwareserial line, or SPI or the like is a good means for spreading out the workload. I've started designing a DC motor controller that would talk over i2c, and have started on a serial-controlled 4-axis stepper driver, but with no micro-controller. I get where you're going, and it makes sense.

I suggest adding to the serial protocol section the ability to 'bounce' your motor setup request over to the motor controller, via i2c, and when the time comes to move the motor, simply send as small a command as necessary. Of course, you still need to wait until the motor stops moving...

If you do that, and it's a worthwhile idea, make sure that you wait for a valid response back from i2c that the move has completed, otherwise you will shoot during the move. You would use flags to perform the wait (since i2c is interrupt-driven), much like most other aspects of the main loop.

You will either need to block the serial response back to the host until instant moves are complete, or provide a 'current move status' request to the protocol - otherwise consuming serial clients (PC running slim, or whatever) will never know when the move completed, when doing manual moves. This could lead to issues when you're trying to script out a manual shot sequence.

You can optimize what you're doing slightly by not using a 2D array like that. All the info you need can be stored in a single byte for each motor. The flag as to whether or not to ship the motor over i2c, and the address for each motor on the i2c bus. Since arduino only uses 7 bits as an address...

byte motor_local_control[4] = { 0, 0, 0, 0 };

...

     // if flag is set for sending motor control over i2c
   if( ( motor_local_control[motor] >> 7 ) ) {
         // send 'start move' request to i2c device
      i2c_send_motor_move( motor_local_control[motor] & B01111111 );
   }

Your idea is sound, I would just suggest the few changes above. If you intend to use the same i2c device for controlling all motors, you would just need two bytes to hold the data (one for the four flags and one for the i2c address).

!c