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.
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
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
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.
#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.
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.
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++ ?
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?
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
#include <Bridge.h>
#include <Console.h>
#include <Wire.h>
#include <YunServer.h>
#include <YunClient.h>
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *frontWheels = AFMS.getMotor(2);
// You can also make another motor on port M2
Adafruit_DCMotor *rearWheels = AFMS.getMotor(1);
const int ledPin = 13; // the pin that the LED is attached to
int incomingByte; // a variable to read incoming serial data into
// We open the socket 5678 to communicate.
YunServer server(5678);
void setup() {
Serial.begin(9600);
// Bridge startup
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
Bridge.begin();
digitalWrite(ledPin, HIGH);
AFMS.begin(); // create with the default frequency 1.6KHz
// Set the speed to start, from 0 (off) to 255 (max speed)
frontWheels->setSpeed(0);
frontWheels->run(FORWARD);
// turn on motor
frontWheels->run(RELEASE);
//OTHER MOTOR
rearWheels->setSpeed(0);
rearWheels->run(FORWARD);
// turn on motor
rearWheels->run(RELEASE);
server.noListenOnLocalhost();
server.begin();
}
void loop() {
uint8_t i;
YunClient client = server.accept();
// There is a new client?
if (client) {
String command = "none";
digitalWrite(ledPin, LOW);
while (!command.equals("stop")) {
if (client.available() > 0) {
command = client.readString();
command.trim();
Serial.println(command);
if ( command.equals("back") ) {
rearWheels->run(RELEASE);
rearWheels->setSpeed(255);
rearWheels->run(BACKWARD);
}
else if (command.equals("forward") ) {
rearWheels->run(RELEASE);
rearWheels->setSpeed(255);
rearWheels->run(FORWARD);
}
else if ( command.equals("brake") ) {
rearWheels->run(RELEASE);
frontWheels->run(RELEASE);
}
else if ( command.equals("left") ) {
frontWheels->run(RELEASE);
frontWheels->setSpeed(150);
frontWheels->run(FORWARD);
}
else if ( command.equals("right") ) {
frontWheels->run(RELEASE);
frontWheels->setSpeed(150);
frontWheels->run(BACKWARD);
}
}
}
digitalWrite(ledPin, HIGH);
client.stop();
}
}
And my C# code just incase
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace RCController
{
public partial class Form1 : Form
{
byte[] msg;
byte[] bytes = new byte[256];
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public Form1()
{
InitializeComponent();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Down)
{
msg = Encoding.UTF8.GetBytes("back");
try
{
// Blocks until send returns.
int i = s.Send(msg);
}
catch (SocketException z)
{
Console.WriteLine(z.Message);
}
}
else if (e.KeyCode == Keys.Up)
{
msg = Encoding.UTF8.GetBytes("forward");
try
{
// Blocks until send returns.
int i = s.Send(msg);
}
catch (SocketException z)
{
Console.WriteLine(z.Message);
}
}
else if (e.KeyCode == Keys.Left)
{
msg = Encoding.UTF8.GetBytes("left");
try
{
// Blocks until send returns.
int i = s.Send(msg);
}
catch (SocketException z)
{
Console.WriteLine(z.Message);
}
}
else if (e.KeyCode == Keys.Right)
{
msg = Encoding.UTF8.GetBytes("right");
try
{
// Blocks until send returns.
int i = s.Send(msg);
}
catch (SocketException z)
{
Console.WriteLine(z.Message);
}
}
else if (e.KeyCode == Keys.ShiftKey)
{
msg = Encoding.UTF8.GetBytes("brake");
try
{
// Blocks until send returns.
int i = s.Send(msg);
}
catch (SocketException z)
{
Console.WriteLine(z.Message);
}
}
}
private void connexionToolStripMenuItem_Click(object sender, EventArgs e)
{
IPAddress[] IPs = Dns.GetHostAddresses("192.168.240.1");
s.Connect(IPs[0], 5678);
msg = Encoding.UTF8.GetBytes("This is a test");
try
{
// Blocks until send returns.
int i = s.Send(msg);
}
catch (SocketException z)
{
Console.WriteLine(z.Message);
}
}
private void deconnexionToolStripMenuItem_Click(object sender, EventArgs e)
{
msg = Encoding.UTF8.GetBytes("stop");
try
{
// Blocks until send returns.
int i = s.Send(msg);
}
catch (SocketException z)
{
Console.WriteLine(z.Message);
}
s.Disconnect(true);
}
}
}
My problem isn't with the output of my command cause that works perfectly, my problem is with the 2 seconds delay between my soft and the arduino giving the command. I tried different approach in my arduino code like, changing from a string to convert to a Int and switching my if to a switch.. case and the effect is still there. I even tried changing my string to a char and the 2 seconds delay is always there.
PS: Something else that I tried is using telnet as my command giver instead of my c# program and the delay remains.