I want to control servos of my wifi enabled robot using the arrow keys of my control node.
Currently I have the robot communicating with the node viva puTTY (telnet window) over a wifi connection. I can parse and control the robot with all other word commands I have however I wish to increment the speed slightly each time an arrow keys are pressed. I understand there is no ASCII code for the keys and they send two bytes instead of the standard one byte for other ASCII keys. Is there a method where I can achieve this ?
The code I am using to test looks like this
//-------Headers---------------------------------------------------------
#include <SPI.h>
#include <WiFi.h>
#include <Wire.h>
//-------Varriables---------------------------------------------------------
char ssid[] = "TEST NETWORK"; // Broadcasted SSID
int status = WL_IDLE_STATUS;
WiFiServer server(23); // Default Port 23
boolean alreadyConnected = false; // Flag to detect if already connected
char ch ='0';
//-------Setup---------------------------------------------------------
void setup() {
Serial.begin(9600); // Initialize Serial 9600 BAUD
while (!Serial) {;} // Wait for Serial to connect
if (WiFi.status() == WL_NO_SHIELD) { // If WiFi shield is not detected
Serial.println("WiFi shield not present"); // Print error to Serial
while(true); } // Lock Up and wait for reset
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid); // Start session for given SSID
delay(10000); } // Wait 10 seconds for response
server.begin();
printWifiStatus();
}
//-------Main Loop---------------------------------------------------------
void loop() {
WiFiClient client = server.available();
if (client)
{
if (!alreadyConnected)
{ client.flush();
Serial.println("Laptop has connected to Arduino");
client.println("Hello Laptop, From Rover!");
alreadyConnected = true; }
while(client.connected())
{ if (client.available())
{
ch = client.read(); //Read Byte
if((int)ch == 279165)
{ Serial.print("UP ARROW RECIEVED");
}
Serial.print((int)ch);
}
}
delay(1000);
client.flush();
ch = '0';
}
}
You're reading one byte and then check for a long integer constant?
You have to read byte after byte. If you're recognizing the start byte of the arrow key sequence, store that information in a status variable. In the next round check if the next character received is one the second characters in the arrow key sequences. If not reset the status variable to the default value.
Sorry reading the long integer was just something I was playing around with while trying to get this.
I tried treating the code as two seperate bytes earlier and it didnt work. But oddly treating the key as three bytes seems to work.
Because all data is transferred as bytes. This is not oddly, this is how everything works. The first byte (27) is the Escape character which initiates a special sequence.
Your code is not as robust as it might be though:
{ if (client.available())
You're testing if one character is available at least but afterwards you're reading up to 3 characters without checking again if one is available. Because usually these characters are sent in the same packet in a telnet session, this will seldom crash your sketch but if the client side is not a human typing in on a keyboard (but a program automating things a bit), you might get a problem.
I'm working on a very similar project as to that outlined here. New to the Arduino world and enjoying it so far!
I want to be able to control a number of servo's by sending keyboard keystrokes i.e. not having to press the enter key each time I want to increment servo position. Currently in the early stages of development; I've used the code supplied by MF4040 and adjusted it to my own needs. I've started with 2 servos, which increment/decrement their position on pressing the WASD keys (as shown in code below).
I'm connecting to the arduino via a telnet connection using PuTTY...
//-------Headers---------------------------------------------------------
#include <SPI.h>
#include <WiFi.h>
#include <Servo.h>
//-------Varriables---------------------------------------------------------
char ssid[] = "Addon"; // Broadcasted SSID
char pass[] = "mypass";
int status = WL_IDLE_STATUS;
WiFiServer server(23); // Default Port 23
boolean alreadyConnected = false; // Flag to detect if already connected
Servo servo0;
Servo servo1;
Servo servo2;
int servo0pos, servo1pos = 90;
//-------Setup---------------------------------------------------------
void setup()
{
Serial.begin(9600); // Initialize Serial 9600 BAUD
Serial.println("'WiFi Servo Control WASD keys' loaded"); //To let me know whats loaded
while (!Serial) {;} // Wait for Serial to connect
// Check WiFi shield is connected
if (WiFi.status() == WL_NO_SHIELD)
{ // If WiFi shield is not detected
Serial.println("WiFi shield not present"); // Print error to Serial
while(true); // Lock Up and wait for reset
}
// Attempt to connect to Wifi network:
while ( status != WL_CONNECTED)
{
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass); // Start session for given SSID
delay(10000); // Wait 10 seconds for response
}
server.begin(); // Start the Server
printWifiStatus(); // Print Connected Status
servo0.write(servo0pos); //set initial servo position
servo1.write(servo1pos);
servo0.attach(6); //the pin for the servo control
servo1.attach(8);
}
//-------Main Loop---------------------------------------------------------
void loop()
{
WiFiClient client = server.available(); // Wait for a new client
// When the client sends the first byte, say hello:
if (client)
{
if (!alreadyConnected)
{
client.flush(); // clear out the input buffer:
Serial.println("Laptop has connected to Arduino");
client.println("Hello Laptop, From Tri-Track!");
alreadyConnected = true;
}
while (client.connected())
{
while (client.available())
{
if (client.available())
{
char input = client.read(); // Read the bytes incoming from the client
Serial.write(input); // Echo the bytes to the server
delay(2); //slow looping to allow buffer to fill with next character
switch (input)
{
case 'w':
servo0pos = servo0pos + 30;
servo0.write(servo0pos);
break;
case 's':
servo0pos = servo0pos - 30;
servo0.write(servo0pos);
break;
case 'a':
servo1pos = servo1pos + 30;
servo1.write(servo1pos);
break;
case 'd':
servo1pos = servo1pos - 30;
servo1.write(servo1pos);
break;
default:
delay(5);
}
if (servo0pos > 180) //Let's servo position values stay in scope.
{
servo0pos = 180;
}
if (servo1pos > 180)
{
servo1pos = 180;
}
if (servo0pos < 0)
{
servo0pos = 0;
}
if (servo1pos < 0)
{
servo1pos = 0;
}
input = '0'; //clears user input
}
}
}
}
}
//-------Print WiFi Status Subroutine-------------------------------------------------
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
I know my code is less than robust! Still learning!
I want to be able to change servo position on a single keystroke and not need to hit the Enter key each time
If anyone on this thread could give me a helping hand it would be much appreciated!
At the moment I can adjust servo position on entering W,A,S,D followed by a carriage return into the Telnet client. I want to be able to read if the keys are being pressed in real time and adjust servo position accordingly i.e. not have to hit 'Enter' after each keystroke.
"the Telnet client" doesn't tell us anything. You need to be more specific.
I'll try my best...
Once the serial connection to my uno/wifi shield is up and I can see that the shield has connected to my network, I'm using PuTTY to set up a Telnet client to connect to my arduino's IP address on Port 23:
if (servo0pos > 180) //Let's servo position values stay in scope.
{
servo0pos = 180;
}
if (servo1pos > 180)
{
servo1pos = 180;
}
if (servo0pos < 0)
{
servo0pos = 0;
}
if (servo1pos < 0)
{
servo1pos = 0;
}
It would probably be a good idea to constrain the values BEFORE writing them to the servos.
It would definitely be a good idea to use Tools + Auto Format to fix the indenting in your code.
It would definitely be a good idea to explain what the problem is. If the issue is that you need to hit the enter key after each letter, you need a different telnet client - one that automatically sends each letter as a packet, which might be hard to find, as most of the time, you do NOT want to send one letter per packet.
It would probably be a good idea to constrain the values BEFORE writing them to the servos.
It would definitely be a good idea to use Tools + Auto Format to fix the indenting in your code.
Ahh yes, that is a good idea. Thank you!
If the issue is that you need to hit the enter key after each letter, you need a different telnet client - one that automatically sends each letter as a packet
This is the issue. I'll see what I can find
Thanks for your help.
Edit: Done it!! For anyone browsing this thread in the future. PuTTY has a 'Local Line Editing' option under the 'Terminal' tab, select 'Force Off'