Problem Serial port

Hello guys,

Hardware used: Arduino uno, linear actuator, 2 forces sensors, 2 amplifier module (for the sensors), a jetson TX1

What i'm trying to do: Control a stick (a mower stick) within 2 modes:

  • power steering mode, the user will press the stick, sensors would recognize the pressure added on the stick and move in the wanted direction
  • Autonomous mode, the TX1 will send PWM signal on the arduino, the arduino will copy it and send it back to the linear actuator

What is my problem? Within my program, there is one function where i send the pwm signal to the actuator. In that function, for debugging purpose, I'm sending some data. My program then work, the linear actuator follow the motion of the stick. I'm pushing forward, it goes forward.

But when I comment the Serial.print line, it will go forward but won't stop. And won't go into the loop() any longer.

Here is the function:

void moveServo() {
 

  #ifdef DEBUG
      // Serial.println("ca marche avec serial");
   #endif
   
   
 /*
  * Function which allow the linear actuator to move by step of 5 us ~ 1°
  */

 
 if (cPos[1] < gPos) { 
   cPos[0] = cPos[1];
   cPos[1] += 5; // modifier tdelay en conséquence
   cPos[1] = constrain(cPos[1],1000,2000);
   myservo.writeMicroseconds(cPos[1]);// 70 = neutral position  
 }
 
 if (cPos[1] > gPos){
   cPos[0] = cPos[1];
   cPos[1] -= 5; 
   cPos[1] = constrain(cPos[1],1000,2000);
   myservo.writeMicroseconds(cPos[1]);
 } 
 //if (cPos == gPos) // nothing
 myservo_movetime = millis() + tDelay;
 
}

And for the whole code: GitHub - Mildred34/Project-06-18

So I'm bit stuck to find from where my problem comes, that's why i'm asking your help. I was thinking about maybe a problem of timer?

I'm using the timer2 for an interruption function to read the data from the sensor each 0,1s. And the timer1 used by the servo library.. And also the timer0 for the millis() function. Every timer in fact.

I'm looking forward hearing from you!

Please post a complete program.

And to make it easy for people to help you please modify your post and use the code button </> so your code looks like this and is easy to copy to a text editor. See How to use the Forum

...R

Raever:

  myservo_movetime = millis() + tDelay;

Never add to millis(), always subtract and compare to avoid wrap around errors.

So you will see my whole code here on github: GitHub - Mildred34/Project-06-18

Raever:
So you will see my whole code here on github: GitHub - Mildred34/Project-06-18

If you want help here please post the code here.

...R

I'd like to but my post is too long for one message. So, I thought put it one github was good. Anyway, here is the code in a text file.

I took into account that millis() return a unsigned long value. But it was not the issue. I'm still thinking that it must be a timer issue. I'll look into that.

Raever

Arduino_code.txt (12.7 KB)

The code in your program

void moveServo() {
  
   #ifdef DEBUG
    /*if (Serial.available() > 0){
        Serial.println("ca marche avec serial");}*/
    #endif

Is not the same as the code you cited as showing the problem in your Original Post

void moveServo() {
 

  #ifdef DEBUG
      // Serial.println("ca marche avec serial");
   #endif

Which version of the code is causing the problem?

And when you attach a file it makes life easier if you post it as a .ino file

...R

Sorry didn't know about the .ino. I'm new on the forum. (now you can find it in .ino in attached file)

So with both version, its make my program act as I said in my first message. It's always when I put my Serial.print in comment that it doesn't work. When it's uncommented, it works fine.

Raever

SmoothControlAuto_micro_3.ino (12.7 KB)

Try commenting out the Serial.print line and adding a short delay() immediately after it - perhaps delay(20); - but try different values if necessary.

If that works you will know that the Serial.print() is helping by wasting time.

Then you/we can start to consider why that might matter.

...R

I tried this with a delay of 1,20,100, it still works.

#ifdef DEBUG
    if (Serial.available() > 0){
        Serial.println("it works with serial");}
        delay(1);
    #endif

And if I do that:

#ifdef DEBUG
    /*if (Serial.available() > 0){
        Serial.println("it works with serial");}*/
        delay(1);
    #endif

It doesn't work.

So it may not be a problem of small delay created by the serial.print(), otherwise it wouldn't have worked with delay and serial in the same time. :confused:

The version that you say does not work only has a delay() of 1 millisec. I suggested 20, and more might be useful.

I can't see any value in testing different delay() periods in the version that works. They are unlikely to cause it to stop working.

...R

Yes I tried with 1ms, 20 and 100 also with the serial commented version.

Raever:
Yes I tried with 1ms, 20 and 100 also with the serial commented version.

I wish you had said that in Reply #9 and saved us all a lot of time.

Then it seems as if the "benefit" of the Serial call is not simply the time it wastes.

I can't make sense of your program at all. Can you write a description of what each function is intended to do? And please use the AutoFormat tool to indent your code consistently for easier reading.

I suggest you greatly simplify the program and in doing so it may become obvious what is the critical factor.

Have you checked carefully to ensure that you are not anywhere writing (or reading) past the end of an array?

...R

Yes, I'll simplify my code, clear the unnecessary. Just to put only the essential. It'll be simpler to find where it stucks.

It'll take some time then I'll come back.

Hello again,

So you will find a more commented version in the attached file. Besides I'll describe you a little more the functions of my program.

  • First the setup

Bring the throttle lever to the neutral position. Wait for the user to bring out the lever.

Tare the sensors. (I'll remove this afterwards just to avoir tare everytime i launch the script)

Wait the user to bring back the lever.

Set up the interruption on the timer 2.

  • The main loop

Call a the function test_mode every 100ms, then call one of this function:
mode_auto, mode_manuel

  • test_mode

Determine if we have to use the manual or autonomous mode depending
on the data we get from the sensors.

  • mode_auto

For now it's just a sweep function.

  • mode_manual

When the user push the lever forward, the linear actuator push it forward.
And vice-versa. For sending new PWM values, to the linear actuator. It calls the function move_servo.

  • move_servo

Depending on the goal position (2000 if we want to go forward, 1000 backward), the move_servo will send a pwm_signal by incrementing (or decrease)the current_position of 5

So, now the problem occur when whether I add a Serial.print in move_servo or within the if statement inside the mode_manual function :

if (bufferR[2] > 2000 && bufferR[2] > bufferL[2] + 500 && bufferR[2] - bufferR[1] < 5) or if (bufferL[2] > 2000 && bufferL[2] > bufferR[2] + 500 && bufferL[2] - bufferL[1] < 5).

For instance, if there is a serial.Print inside the move_servo function, my program works for both direction going forward or backward. If I add a Serial, inside the first if but not in the other, it'll work only for the backward direction. And the other only in the forward direction.

You have to know that this if statement detect in which direction the linear actuator has to move depending on which direction the user pushes the lever.

SmoothControlAuto_micro_rectified.ino (14 KB)

I thought you were going to simplify the program - by which I had in mind removing a great deal of code until the core part (the forwards and backwards movements) works properly. From that point you can then add back extra features checking all the time to see if any of them cause a problem.

You have a lot of variables with short cryptic names such as dF, cPos and gPos. I find that using meaningful names makes it much less likely that I make a mistake as well as making it possible to understand the code quickly after a break from it.

While it is probably not related to your present problem you should not use addition with millis(), such as this

myservo_movetime = millis() + tDelay;

You should always use subtraction to avoid a problem when millis() rolls over - as illustrated in Several Things at a Time

...R

Robin2:
While it is probably not related to your present problem you should not use addition with millis(), such as this

myservo_movetime = millis() + tDelay;

You should always use subtraction to avoid a problem when millis() rolls over - as illustrated in Several Things at a Time

The OP is ignoring the above advice since #2.

Whandall:
The OP is ignoring the above advice since #2.

I'm sorry but I replied you since #5 "I took into account that millis() return a unsigned long value. But it was not the issue. I'm still thinking that it must be a timer issue. I'll look into that." I put all my time values to unsigned long in respond to your reply. Thought it would solve this millis problem.

In fact, I had this problem since my program was only containing the manual mode. At this point i can't reduce the program more. I would add this short version too.

For the short variable, cPos is for current position, gPos for goal position and dF for differential force. I would write it back in the short version with full name.

So you'll find the only manual version in the attached file. Can't reduce it more.
The problem keeps pointing its nose.

Interesting thing is if I put a serial.print in one of the location that I told you but I used a Serial.end() at the end of the setup, it still works.. :o

Thought it would have behaviored as if i would not have added a serial.print().

What do you think about that? Do you know where can I have access to the library of the serial. I might be interested to read how its code works.

SmoothControlAuto_micro_rectified_reduced.ino (8.65 KB)

Raever:
"I took into account that millis() return a unsigned long value. But it was not the issue. I'm still thinking that it must be a timer issue. I'll look into that."

So why did you leave the incorrect additon in your code?