GoPro Zip-Line Project - Problem getting it to work with App / Servo / Bluetooth

Hi Everyone,

Over the last couple of weeks I created/designed a Zip-Line and printed it with my 3D printer. I also soldered my own PCB with an Arduino Nano V3.0 (Atmega 328), a Bluetooth module (HC-05), a 5V regulator (TO-220), some capacitors and a connection for 1 or 2 servos (TowerPro MG90S). I also use two of those yellow DC motors (gear ratio 1:48 with around 180 RPM at 5V) which are connected to a L9110S motor module. I am powering the PCB with a 7.4V LiPo (2-cell).

So how do I want it to work? I want to use an App I created with MIT App Inventor to move the Zip-Line along a rope. I already got that working and it looks/works great - My Android phone connects via Bluetooth to the App and I can press two buttons to move the Zip-Line along the rope (forward/backward). I also have a slider to change the speed of the motors (I am using PWM pins 6 & 11). So far so good. Now I wanted to go a step further and have my GoPro “hanging” from the Zip-Line. I looked up some tutorials, watched lots of videos and implemented the newly learnt stuff into my App and the code. I am using a slider for the servo movement on the App and the servo is connected to PWM pin 3 on the Arduino Nano. I am not a programmer and that’s were I have some problems and I really hope that you guys can help me out.
Here comes my question: I actually can get the code and the App (kind of) working, but the servo always seems to “react” to everything I do on the App. For example: When I press the button down to move the Zip-Line forward the servo “jitters” and the motors don’t react. Sometimes the motors do move, but it is unpredictable. Same happens while moving the slider for the speed. How can I change my code so that the servo does not interfere with the motors module? I think it might have something to do with the Bluetooth signal(s), but I am not sure. Maybe I need to move the servo to a non-PWM pin? I already tried lots of different things I read on Google or here on the Arduino Forum, but nothing seemed to work for me. I even gave a different servo library a try (ServoTimer2), but there I can’t even get the servo to move properly (I changed the pinout for for the motor module to PWM pin 6 & 9 and the servo to 5).

Here is my code:

#include <SoftwareSerial.h>

#include <Servo.h> 
Servo myservo;

const int M1APin=6;
const int M1BPin=11;

const int sig=2;
const int Eco=4;

int speed=205;

const int BTPinR=7;         // Recieve pin
const int BTPinT=8;         // Transmit pin

SoftwareSerial BT(BTPinR,BTPinT);    

String readString;
char Mode='A';      
char ch,speedchar;

void setup() { 

  myservo.attach(3);
  
  BT.begin(9600);      
  Serial.begin(115200);
  
  Serial.println("press '0'~'9' : setup speed");
  Serial.println("press 'S' : stop");  
  Serial.println("press 'F' : front");
  Serial.println("press 'B' : back");   

  pinMode(sig,OUTPUT);
  pinMode(Eco,INPUT);
}

void loop() {

  if (readString.length()>0) {  
    readString="";
  }
  
  if (readString[0]=='P') {
    speedchar = readString[1];
    speed = map(speedchar,'0','9',155,255);
  }
  
  while (BT.available()) {  
    delay(1);   
    ch = BT.read();
    readString+=ch;
  }

  if (Mode=='A') {                     // Manual mode 
    if (readString=="ST") { 
      stop(); 
    } else if (readString=="FW") {    
      forwardPWM(); 
    } else if (readString=="BW") {   
      backwardPWM();
    }
  }

  if(BT.available())                 
  {
    int servopos = BT.read();
    Serial.println(servopos);
    myservo.write(servopos);
  }
}

void forwardPWM() {                   // Forward
  analogWrite(M1APin,speed);
  analogWrite(M1BPin,0);
}

void backwardPWM() {                  // Backward
  analogWrite(M1APin,0);
  analogWrite(M1BPin,speed);
}

void stop() {                         // Stop
  pinMode(M1APin,OUTPUT);
  pinMode(M1BPin,OUTPUT);
  digitalWrite(M1APin,LOW);
  digitalWrite(M1BPin,LOW);
}

If you need any additional information (like a screenshot of my blocks in MIT App Inventor), just let me know. As I already said, I am not a programmer and I am not quite sure were exactly the problem is (I just have the few guesses I mentioned above). I know there might be an easy solution to my question(s) and/or an easy workaround, so feel free to let me know anything that might be able to point me in the right direction. I am looking forward to your replies and to getting my Zip-Line to work properly.

Once the project is successfully finished, I plan to make it open source, so everyone can built my Zip-Line.

Thanks a lot,
Annika

Hi,

Welcome to the forum.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
Please show your power connections as well.

How have you got the servos powered, they can need up to 1A and if they are loaded while stationary, can be consuming more current than still and unloaded.

Have you monitored the power supply while using the servos?

Thanks Tom… :slight_smile:

  if (readString.length()>0) { 
    readString="";
  }

  if (readString[0]=='P') {

If the String has any data in it, remove all the data. Then, if the first (non-existent) character is a P, do something.

How likely is THAT to be true?

    speed = map(speedchar,'0','9',155,255);

Your from range is 10. Your to range is 100. Simple multiplication and addition gets from one range to the other, without the need to divide anything. map() is overkill for such a simple translation.

  while (BT.available()) { 
    delay(1);   
    ch = BT.read();
    readString+=ch;
  }

While there is some data to read, stuff your head in the sand for a while. Why?

    int servopos = BT.read();

You will be reading characters, not an integer value. What is the use of sending the servo to '5'?

Hi Everyone,

Thanks to TomGeorge & PaulS for replying and trying to help me find an answer to my problem/question(s).

TomGeorge - I attached two pictures that show my PCB. One shows it the way I got it printed (screenshot of the Gerber files) and the other shows the PCB schematics. Are those good enough? I used Fritzing and I think I can only provide files that you can open there, so I do not know how useful that’ll be to you…
I have molex-like connections/pins soldered onto my PCB. The Lipo battery plugs into one of those, as well as the rocker switch I use for turning the whole PCB on and off. The motor module is also connected to the PCB through molex-like connections/pins. The power from the Lipo goes into a capacitor, then directly into the Arduino Nano and to the 5V regulator. There is another capacitor and then the motor module, Bluetooth module as well as the servos are getting their 5V. Doesn’t seem too much, right? I am using the 7.4V 360mAh 2 cell 20C Lipo battery from Rhino. Right now I am only trying to get one servo to move (only one is plugged in). Maybe later I’ll try to create a “real” gimbal that can pan and tilt, but for now I only want the GoPro to pan/turn from left to right. I’ll definitely try to hook up my oscilloscope and have a look at the power supply. Thanks & I’ll let you know how it went.

PaulS - I think I might need some more help to make sure I understand your comments correctly.

I do get what you are saying about the first piece of code. I just don’t know how to change it into something more “logical”? 'Cause it works they way I intended to work. Can you please show me how I should change it?

I do agree that map() is a bit over the top, but it wouldn’t change anything of the outcome if I leave it like this, right?

  while (BT.available()) { 
    delay(1);   
    ch = BT.read();
    readString+=ch;
  }

And for this, should I just delete the delay part?

  if(BT.available())                 
  {
    int servopos = BT.read();
    Serial.println(servopos);
    myservo.write(servopos);
  }

I thought that this line (int servopos = BT.read():wink: is necessary in order to later move the servo into the “desired” position. The received number (from Bluetooth) is saved to servopos. The next line then says serial print the number servopos received from Bluetooth. What exactly is wrong there? I basically want the servo to move into the position I selected with the slider on my App (that’s works!), but I do not want the servo to “react” to anything else I do on the App (like moving the slider for the speed of the motors). I probably wouldn’t mind if the servo sometimes “jitters”, but that “jittering” blocks the thing I actually wanted it do do (like changing the speed, move the motors forward, backward, stop the movement). Should I send some pictures of my blocks (code) in MIT App Inventor? This might very well be were something’s going wrong…

I had to set up a new account here, but I am the one who wrote the post at the top. The new account will be the one from which I am going to write all further posts. Hope it does not cause any confusion.

Thanks for welcoming me & thanks again for help,
Annika

Hi,
This is not enough.
b3f14f846f9f3d66ddbdb95fd3c4ec177ae97eff.jpg
Where is the L9110S motor module, motors and the power supply and the servos etc.
Please a FULL schematic that shows how everything is connected including power supplies.
A picture of a hand drawn circuit in jpg, png? (Please no fritzy, as you can see it is just about impossible to follow.)

Have you coded this in stages, do you have working code for just the motor operation, another for just the servo operation, another for just bluetooth connection, etc etc.

You should be coding in stages and getting each stage to work before they are combined.
Also a link to specs and data on the servos and motor and motor module please.

Thanks Tom… :slight_smile:

TomGeorge - I can see the problem with the Fritzing schematic and I'll try to draw it by hand with all the details you (and everyone else) will need. Would it help as well if I would take a picture of the "real" assembled PCB?

I did code my code in stages and I have some other projects that use part(s) of the code (or something similar). For example: I have a small 3D printed car which I can drive with another App I created with MIT App Inventor. There I use the same Bluetooth module (HC-05) and two of the same motor modules (L9110S). The connections to the Arduino (and the whole PCB) are quite similar in their design and layout to the one I created for the Zip-Line. The small car works great. I do have a shorter code (without the servo stuff) for the Zip-Line and an App that just connects via Bluetooth and makes the Zip-Line move forward & backward & stop along a rope. That works great and without any trouble. So that's why I think that something went wrong when I added the code (and blocks!) for the servo (the code for the servo works fine on it's own as well!).

This is the servo I am using right now: MG90S

I also tried this servo: SG90 - but since the GoPro is hanging down from the Zip-Line I chose the MG90S, they feel "stronger".

The motors I use: Yellow Motor

The motor module that I use: L9110S

Are those Links good enough?

Thanks again, Annika

but it wouldn't change anything of the outcome if I leave it like this, right?

The code will take longer than necessary to execute. Get rid of the delay().

I thought that this line (int servopos = BT.read();) is necessary in order to later move the servo into the "desired" position. The received number (from Bluetooth) is saved to servopos.

That is true, BUT "the received number" if you send "90" is '9' which is 57. If you want to send 9 and have the servo move to 57 degrees, you don't need to change anything. You just need to be aware that sending 90 will not move the servo to 90 degrees. The only positions you'll be able to send it to are 48 to 57 degrees.

If you want to send "90" and have the servo move to 90 degrees, you need to handle the incoming data differently. The lazy way is to use the parseInt() method, instead of the read() method.

Hi Everyone,

TomGeorge - I attached the picture of my circuit below. I tried to make it as detailed as possible - hope that works now and that you (and everyone else) can understand my circuit. If you have any further recommendations/questions or if you find any flaws, please let me know.
Just wanted to let you know, that I am using one more capacitor on my real PCB, but that’s just due to the small shape I chose for my PCB (and 'cause I didn’t want to use any vias), but that shouldn’t change anything…

PaulS - I erased the delay(1) part in my code, but it didn’t change/solve my problem. I am about to look into the parseInt() method - haven’t heard of it, but that doesn’t mean anything since I am not a programmer. Thanks for mentioning it! Even tough the code might not be super correct (as you mentioned in your post) the servo does move it’s full 180 degree when I move the slider on my App (might be thanks to the stuff happening in my App). Nonetheless I am looking into every hint I get.

I was wondering and thinking about something else and I hope I do not make a total fool out of me by asking that question:

Is it possible to set the Bluetooth waves to fixed frequencies? So I could have one for controlling the motor module and one for the servo(s)? If is is possible, how would I do that?
I still think the servo is somehow (sometimes!) reacting to signals I send to the motor module and that’s what is causing it to “jitter” and the motors to not react at to the signal. I tried changing those numbers in: BT.begin(9600); and Serial.begin(115200); - but it didn’t solve my problem…

Thanks again,
Annika

Hi, Thanks..

If you remove the bluetooth, and enter the commands that would be received by the BT, does it work?

Tom... :)

This is an addition to my question about the Bluetooth waves and its frequencies: I attached a pictures with the blocks from MIT App Inventor that are relevant to this (I left the ones for connecting to Bluetooth, etc. out). Maybe I can change something regarding the Bluetooth communication and the signals? I do played around with different blocks and tried different things, but nothing good came out of it. Maybe you guys have an idea?

Tom, I haven’t tried that - that’s a great idea and I can’t believe I didn’t try that already. Will do it now & let you know how it went…

Hi Everyone,

I had to edit the picture of my circuit. There was a small mistake: B-IB & A-IB are connected to D6 and not to D5 as I wrote next to the motor module (the wiring on the picture was correct though) - Sorry, if I caused any trouble/confusion…

Tom - I did try it and I would say it works without the Bluetooth stuff. I used the Arduino example code “Sweep” for the Servo movement. “Sweep” works great on its own and when I run the whole code (without Bluetooth stuff) is does move while the motors are moving. BUT it does stop after going through its code for like 3 seconds before it does it again - the motors never stop moving. This does not happen while just running “Sweep”. Would you know why? It does confuse me a bit… Still the servo is able to move while the motors move, does this mean I am right and there is something going wrong with the Bluetooth signals? Have you had time to look at my circuit picture?

#include <Servo.h>

Servo myservo;

int pos = 0;

const int MIAPin = 11;
const int MIBPin = 6;

int speed = 255;

void setup() {
  myservo.attach(3);
  pinMode(MIAPin, OUTPUT);
  pinMode(MIBPin, OUTPUT);
}

void loop() {
  for (pos = 0; pos <= 180; pos += 1) { 
    myservo.write(pos);
    delay(10);             
  }
  for (pos = 180; pos >= 0; pos -= 1) { 
    myservo.write(pos);
    delay(10);
  }   
  forward();
  delay(2000);
  backward();
  delay(2000);
}

void forward() {
  analogWrite(MIAPin, speed);
  analogWrite(MIBPin, 0);
}

void backward() {
  analogWrite(MIAPin, 0);
  analogWrite(MIBPin, speed);
}

PaulS - I looked into the parseInt() method and I modified my code to be able to use it instead of my other lines of code that “miraculously” did what I wanted them to do, but it didn’t change anything… However, thanks for mentioning it anyway! Do you have any thoughts/ideas regarding my Bluetooth frequency questions? How could I modify my code or blocks?

Thanks again,
Annika