Go Down

Topic: RC Car controlled Wirelesly (Read 13399 times) previous topic - next topic

AllSystemGO

Hey Guys,

    I'm pretty news to the whole Arduino scene but I find it really interesting. I just need some pointers on how to accomplish my projects. So before I ask my questions, let me just say sorry if they are "noob" questions and if I seem vague in my explanations. Don't hesitate to ask me to clarify if you guys don't understand.

So here goes. My project looks like this, I bought a RC Car and stripped everything in there and would like to be able to control the car using the Yun Wifi.

1- What is the best way to control the car, through the Web Server ? I don't know if it's the best way, it looks laggy.

2- If the web server is the best how do I create a web interface and send the commands to the yun?

Thank you

PS: If I posted in the wrong thread sorry about it. Just move it.

federicofissore

web server is indeed laggy at the moment (it's not its fault actually, in another thread there is a more complete explanation)
I'd go with yunserver and yunclient instead, that makes you talk more directly to the sketch

AllSystemGO

Thank you for the help, and by yunserver yunclient you mean SSH and then Telnet ???

federicofissore

At your choice. If you call server.listenOnLocalhost() then yes
If you call server.noListenOnLocalhost() it will start listening on port 5555 (or a port of your choice) on yun's public IPs

AllSystemGO

I'm really sorry to come back with this but I still don't get how to talk to the arduino, without latency. I've been reading alot lately on that and what I can see is people seem to create a WebServer and talk to the arduino this way. Is that the best way to do it ? If not how do I create a UI with a foward and backward button and maybe 2 other button to speed up the car and talk directly on the Arduino?

Right now I'm able to connect SSH and Telnet to the board and send commands like F to make it go foward and it works really good.

If any of you don't feel like explaining a link to a complete tut would be good enough for me.

Thank you again and sorry to be bothering you guys.

federicofissore

Just to be sure: are you saying you set up a YunServer with noListenOnLocalhost(), tried to connect to the yun and it failed?
I've just coded this
Code: [Select]

#include <YunServer.h>
#include <Bridge.h>
#include <YunClient.h>

YunServer server(5678);

void setup() {
  Serial.begin(9600);

  // Bridge startup
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  Bridge.begin();
  digitalWrite(13, HIGH);

  server.noListenOnLocalhost();
  server.begin();
}

void loop() {
  YunClient client = server.accept();

  // There is a new client?
  if (client) {
    String command = "none";
    while (command.indexOf("stop") != 0) {
      if (client.available() > 0) {
        command = client.readString();
        client.print("Received: ");
        client.print(command);
      }
    }
    client.stop();
  }
}


I can then open a terminal and write
Code: [Select]

federico@smilzo:~$ telnet 192.168.240.1 5678
Trying 192.168.240.1...
Connected to 192.168.240.1.
Escape character is '^]'.
Hello world!
Received: Hello world!
Say hi!   
Received: Say hi!
stop
Received: stop
Connection closed by foreign host.

AllSystemGO

I might have explain myself wrong.

Right now I can control my car using this code.

Code: [Select]

#include <Console.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Or, create it with a different I2C address (say for stacking)
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61);

// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
// You can also make another motor on port M2
Adafruit_DCMotor *myOtherMotor = AFMS.getMotor(2);

const int ledPin = 13; // the pin that the LED is attached to
int incomingByte;      // a variable to read incoming serial data into

void setup() {
 Serial.begin(9600);           // set up Serial library at 9600 bps
 Serial.println("Adafruit Motorshield v2 - DC Motor test!");

 AFMS.begin();  // create with the default frequency 1.6KHz
 //AFMS.begin(1000);  // OR with a different frequency, say 1KHz

 // Set the speed to start, from 0 (off) to 255 (max speed)
 myMotor->setSpeed(150);
 myMotor->run(FORWARD);
 // turn on motor
 myMotor->run(RELEASE);

 //OTHER MOTOR
 myOtherMotor->setSpeed(150);
 myOtherMotor->run(FORWARD);
 // turn on motor
 myOtherMotor->run(RELEASE);

 // initialize serial communication:
 Bridge.begin();
 Console.begin();

 while (!Console){
   ; // wait for Console port to connect.
 }
 Console.println("You're connected to the Console!!!!");
 // initialize the LED pin as an output:
 pinMode(ledPin, OUTPUT);
}

void loop() {
 uint8_t i;

 // see if there's incoming serial data:
 if (Console.available() > 0) {
   // read the oldest byte in the serial buffer:
   incomingByte = Console.read();
   // if it's a capital H (ASCII 72), turn on the LED:
   if (incomingByte == 'F' || incomingByte == 'f') {
     myMotor->run(FOWARD);
     myMotor->setSpeed(100);
   }
   if (incomingByte == 'L' || incomingByte == 'l') {
     myOtherMotor->run(FORWARD);
     myOtherMotor->setSpeed(100);
     delay(1000);
     myOtherMotor->setSpeed(130);
     delay(1000);
     myOtherMotor->setSpeed(140);
     delay(2000);
     myOtherMotor->setSpeed(160);
     delay(2000);  
   }
   if (incomingByte == 'R' || incomingByte == 'r') {
     myOtherMotor->run(BACKWARD);
     myOtherMotor->setSpeed(225);
   }
   if (incomingByte == 'C' || incomingByte == 'c') {
     myOtherMotor->run(RELEASE);
   }
   // if it's an L (ASCII 76) turn off the LED:
   if (incomingByte == 'B' || incomingByte == 'b') {
     myMotor->run(BACKWARD);
     for (i=0; i<255; i++) {
       myMotor->setSpeed(i);  
       delay(10);
     }
   }
   //
   if (incomingByte == 'S' || incomingByte == 's') {
     myMotor->run(RELEASE);
     myOtherMotor->run(RELEASE);
   }
 }    
}


So on my Android tablet I have a ssh client I connect using ssh root@192.168.240.1, then I telnet localhost 6571

I send F and my car goes FOWARD. So that part works.

Now what I would like is to create an interface, instead of writing F in a SSH client, that has buttons to make the car go foward.

Hope I'm a little bit clearer now.

federicofissore

If you expose your sketch with a "public" YunServer as in my previous example, you can open a socket from your android to your yun and have your sketch wait for a YunClient connection instead than using Console.
Sockets are quite easy to manage and IMHO it's the most reactive way for controlling a car.

AllSystemGO

Thank you for your help Frederico, I'm not finished and don't understand everything just yet but I think you just send me on the right track.

Thank you again.

federicofissore

Keep us posted: remote controlling is tough, if you report us your progress we will all benefit

AllSystemGO

#10
Oct 21, 2013, 06:45 pm Last Edit: Oct 21, 2013, 07:19 pm by AllSystemGO Reason: 1
Sure thing Frederico I'll be more then happy to make ppl benefit by my project.

One question about the code. And again might be me the problem here.

Code: [Select]

#include <YunServer.h>
#include <Bridge.h>
#include <YunClient.h>

YunServer server(5678);

void setup() {
 Serial.begin(9600);

 // Bridge startup
 pinMode(13, OUTPUT);
 digitalWrite(13, LOW);
 Bridge.begin();
 digitalWrite(13, HIGH);

 server.noListenOnLocalhost();
 server.begin();
}

void loop() {
 YunClient client = server.accept();

 // There is a new client?
 if (client) {
   String command = "none";
   while (command.indexOf("stop") != 0) {
     if (client.available() > 0) {
       command = client.readString();
       Serial.println(command);
       if (command == "OFF") {
         Serial.println("OFF");
         digitalWrite(13, LOW);
       }
       if (command == "ON") {
         digitalWrite(13, HIGH);
       }
       client.print("Received: ");
       client.print(command);
     }
   }
   client.stop();
 }
}


Why is it that I never go in the if (command == "OFF") or "ON" statement?
If I try comand.equals("OFF") or even compareTo doesn't work

UPDATE: Weird thing if I do if (command.indexOf ("OFF") == 0) {

that works.

federicofissore

Because command contains a newline (or carriage return + newline, it depends on the OS)

AllSystemGO

Yeah you are right. Adding command.trim(); worked like a charm.

Sorry for that question!! :)

AllSystemGO

Hey Frederico,

   Ok this is how far I got, right now I'm listening on Socket 5678 like you showed me. I created a little c# project that send stuff over the socket and that works fine, the arduino get's all my commands. But their is a 2 seconds delay between when I press the up arrow and when the car starts turning. So what I would like to know is what could do te delay ? Should I try coding all in c++ ?

Thank you again Frederico

federicofissore

I don't think the problem is in your c# code (but I'll stress test it anyway, just in case)
It's probably on the arduino side even if 2 seconds for such a thing is really a lot. Do you have source code to share?

Go Up