0

I am a beginner in Arduino, I have only basic knowledge and a big appetite :)

I'm working on my cable-cam project. I've made all the mechanical parts by myself, bought all electricity parts through eBay, and everything works fine so far. With the basic RC controller I steer forward / back and I also have a speed potentiometer.

Now there is a question of security: Since cable-cam runing on a rope fastened to two hubs/buildings/trees/piers, up to 40 mph. I would like to have the opportunity to program two points through which the cable-cam cannot overdrive, so that it would not go to the end of the rope and break itself.

THE concept: cable-cam is driven to point A and is marked. Then it is driven to point B and also marked. When the cable-cam reaches point B, it stops and can not go further, but it can go back to point A. And vice versa. Something like a "operation range control points" that can be programmed. Something like this: end points with Hall sensor

THE idea: on a non-powered wheel (for avoiding slippage and incorrect reading of data on the encoder), I'll set an absolute encoder to measure axis rotations and thus calculate the distance in both directions. The encoder would then be connected to the Arduino that would send the ESC signal to stop the engine when it reached that point, A or B. Stopping should be soft, not at the moment. The speed of the cable cam can be significant, so abrupt stoppage would also be a problem.

So...am I pre-ambitious? I need help with code for Arduino.

Parts: RC: Turnigy 9X ESC:Syren 50A and it has an Arduino library, and the encoder:Koyo TRD NA1024NW

  • 1
    tie a string from A to B. the string passes through the carriage of the device. attach a "stopper" at each end of the travel. something like this google.co.in/… .... then use a switch on each side of the carriage to detect the end points – jsotola Dec 16 '17 at 1:01
  • Cannot do that, I need more sturdy solution... – littlerock Dec 16 '17 at 14:53
2

This is a quite high-level question, so I will answer in general terms, skipping the fine details. You can ask here more specific questions once you are implementing the stuff.

Yours is a 10-bit absolute encoder. It can tell you its shaft position with a resolution of 1/1024 revolution. It's way overkill for your application. I suggest you connect only the four most significant bits (pins 9 – 12), which will give you a resolution of 1/16 revolution.

It's better to read the four bits simultaneously. This can be done using direct port manipulation. I would connect pins 9 – 12 of the encoder to pins 4 – 7 of the Arduino respectively. As the encoder outputs are open-collector, you have to enable the pullups in setup():

PORTD |= 0xf0;  // enable pullups on pins 4..7

and you can read the encoder simply as

uint8_t ecoder_value = PIND & 0xf0;

Notice that this will give you a result that is left-aligned. This way you can treat it as an 8-bit Gray code.

Next step is to decode the Gray code. I let you research how to do that, as you can probably find examples, or even ready-made libraries for that.

Next, you have to extend the value to a wider bit length in order to know the absolute position of the cable-cam. The encoder only tells you where you are within a revolution, but it doesn't tell you how many revolutions you did. The extension is done by comparing the current encoder position with the previous one, taking the difference (which can be positive or negative), and adding it to the previously computed absolute position. Something like this:

int32_t absolute_position;

void update_absolute_position(uint8_t encoder_position)
{
    uint8_t old_position = absolute_position;  // extract LSB
    int8_t delta = encoder_position - old_position;
    absolute_position += delta;
}

Beware of the types of the variables. The type of delta, for instance, ensures that the result of the subtraction is wrapped the correct way to yield a number between −128 and +127. Thus, the sign will tell you which is the shortest path (clockwise or counterclockwise) from the previous to the current position.

Note also that you have to call this function frequently enough: more than once per half revolution. Otherwise it won't know which direction the wheel turned. If your loop() runs fast enough (you don't use delay(), right?), you just have to call this function once in loop(). Otherwise you would have to setup a timer interrupt to ensure the updates are frequent enough.

Lastly, you have to define the limits:

int32_t left_limit = INT32_MIN;
int32_t right_limit = INT32_MAX;

// To set the left limit to the current position:
if (user_pressed_the_relevant_button()) {
    left_limit = absolute_position;
}
// and likewise for the right limit.

and condition the maximum speed on the distance to the closets limit. Assuming you store the speed as a signed number (the sign being the direction), you would constrain it to always be between a negative min_speed and a positive max_speed, which could be updated as follows:

// Slow down if close to a position limit.
if (absolute_position - left_limit < BREAKING_DISTANCE) {
    min_speed = map(absolute_position,
        left_limit, left_limit + BREAKING_DISTANCE,
        0, -ABSOLUTE_MAX_SPEED);
} else {
    min_speed = -ABSOLUTE_MAX_SPEED;
}
if (right_limit - absolute_position < BREAKING_DISTANCE) {
    max_speed = map(absolute_position,
        right_limit - BREAKING_DISTANCE, right_limit,
        +ABSOLUTE_MAX_SPEED, 0);
} else {
    max_speed = +ABSOLUTE_MAX_SPEED;
}
speed_to_apply = constrain(requested_speed, min_speed, max_speed);

Note that this makes the speed limit a linear function of the position. You may want to look into easing functions to have a smoother breaking.

  • Thx everyone for your effort to help me!! I am aware that specific absolute encoder is overkill for my project, but I need it because of high rpm count. Cable-cam runs up to 40 mp/h and wheel is rotating up to 1500rpm. I have no problem to use it at lower resolutions. Main point is to free drive cable-cam between two points, in any direction, at any speed. ONLY when cable-cam reach one of predefine points-it stops. Softly. You can manually drive it backwards, but you cannot go beyond that point. – littlerock Dec 16 '17 at 14:59
  • Ufffff guys... This is soooo over me and my knowledge. I belive that I need to outsource somebody for this work... In my head "little devil" told me: " you can do it, you just need two secure points, how hard it can be?" Well...now I know :))) So...if there is anyone willing to do complete code for me...I am sure that we will find some way to compesate that amount of work – littlerock Dec 16 '17 at 14:59
  • @littlerock: You should probably try to find some help close to where you live. At some point you will have to debug and fine tune the firmware, which would require modifying the code and testing on the real hardware. If the person writing the code and the person doing the test are megameters apart, that won't be easy... – Edgar Bonet Dec 16 '17 at 22:16
0

It is quite difficult to say any thing without the actual code, but if you are reading the position of the cam regularly you can implement a "if/else" condition. Some thing like this:

if(position==A)
reverse();
else
continue;

(this is very crude and undefined and there are many ways to improve it) Here position is assumed to be the position of the cam and A is the maximum that can be traversed to. A same condition can be applied in case of the other end as well. (also reverse() is a function that reverses the direction of motion. In addition to this, you can replace reverse() by some thing like stop() and after that check "position" is greater than A call the reverse function till the condition is met. Hope this helped.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.