Offline
Newbie
Karma: 0
Posts: 14
|
 |
« on: February 13, 2013, 12:46:09 pm » |
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'; } }
|
|
|
|
|
Logged
|
|
|
|
|
Switzerland
Offline
Faraday Member
Karma: 69
Posts: 3256
|
 |
« Reply #1 on: February 13, 2013, 12:54:08 pm » |
ch = client.read(); //Read Byte
if((int)ch == 279165)
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.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 14
|
 |
« Reply #2 on: February 13, 2013, 01:04:08 pm » |
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. ch = client.read();
if(ch==27) { ch=client.read(); if(ch==91) { ch=client.read(); if(ch==65) { Serial.print("UP ARROW DETECTED"); } } } Im not sure why this is though
|
|
|
|
|
Logged
|
|
|
|
|
Switzerland
Offline
Faraday Member
Karma: 69
Posts: 3256
|
 |
« Reply #3 on: February 13, 2013, 02:13:51 pm » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #4 on: February 13, 2013, 02:25:42 pm » |
You're reading one byte and then check for a long integer constant? Yeah, but there is a cast to int. 
|
|
|
|
« Last Edit: February 13, 2013, 02:43:18 pm by PaulS »
|
Logged
|
|
|
|
|
Switzerland
Offline
Faraday Member
Karma: 69
Posts: 3256
|
 |
« Reply #5 on: February 13, 2013, 02:40:29 pm » |
@PaulS: you forgot the smiley. At least I hope it wasn't meant seriously.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #6 on: February 13, 2013, 02:43:04 pm » |
@PaulS: you forgot the smiley. At least I hope it wasn't meant seriously. Yeah, I forgot it.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 5
|
 |
« Reply #7 on: March 24, 2013, 08:46:47 am » |
Hi guys, 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!
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #8 on: March 25, 2013, 05:52:33 am » |
If anyone on this thread could give me a helping hand it would be much appreciated! What do you need help with?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 5
|
 |
« Reply #9 on: March 25, 2013, 07:15:44 am » |
What do you need help with? 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. I hope that clarifies? edit: formatting
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #10 on: March 25, 2013, 07:41:58 am » |
At the moment I can adjust servo position on entering W,A,S,D followed by a carriage return into the Telnet client. "the Telnet client" doesn't tell us anything. You need to be more specific.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 5
|
 |
« Reply #11 on: March 25, 2013, 08:19:36 am » |
"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:  As you can see from the image, I open the client and can adjust the servos by entering either W,A,S or D.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #12 on: March 25, 2013, 08:42:29 am » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 5
|
 |
« Reply #13 on: March 25, 2013, 08:57:02 am » |
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' 
|
|
|
|
« Last Edit: March 26, 2013, 08:00:43 am by newb91 »
|
Logged
|
|
|
|
|
|