So I've been working on a few different robot car builds. The other one is using a wifi module communicating with serial interface to arduino. In this one I've got things to work nicely. But on the other one I don't need the extra pins of normal arduino so I'm trying to use a wifi development board(Wemos D1 mini). Basic functionality I've got working, but having hard time to get the data received from android app to a format I can use as a base for switch-case structure.
So the app sends commands to the wifi module / development board as an argument (address/?State=X) where X is like 'F' for forward etc...
Then the wifi module receives this argument and reads it and forwards it to arduino.
Like this:
void HTTP_handleRoot(void) {
if( server.hasArg("State") ){
Serial.println(server.arg("State"));
}
server.send ( 200, "text/html", "" );
}
And finally the arduino reads the data sent by wifi module. And is able to use this data straight as an integer for the switch-case.
Like this:
int command;
...
if (Serial.available() > 0) {
command = Serial.read();
switch (command) {
case 'F': {
if (LastAction != 6) {
forward();
}
break;
}
But when I try to implement the same thing straight on the wifi development board, it gives an error for not being able to read the Argument data to an integer. Because the argument data is a string.
So I read a lot of different things about it but to no end. (Maybe I've been searching for the wrong thing.)
Tried the basics atoi(); -functions and such. But I think I read somewhere the string has to start with a number or it will just give '0' as it did.
So more researching and I think I hit the core of the problem. The wifi board sends the data straight to the serial port with Serial.println. (Which outputs the data as human readable ascii).
So I think the serial connection changes the data type to a format that can be read into an integer and used as such. (Stores the ascii letter as ascii character into an integer). So I've always thought integers were only whole numbers. But can C use letters in place of a number as integer using it's ascii format?
And the six cent question: How to change this type directly on the code of the wifi development board? Or am I better of using another format?
Malagath:
But when I try to implement the same thing straight on the wifi development board, it gives an error for not being able to read the Argument data to an integer. Because the argument data is a string.
Post the full code and error messages.
As a side note: why are you using HTTP to send a single byte? It's a huge waste of resources.
Pieter
You first read the value of the argument as a 'String' and then transfer the first character of it into a char variable.
char state;
if( server.hasArg("State") ){
String State=server.arg("State");
state=State.charAt(0);
}
or even just like this
char state;
if( server.hasArg("State") ){
state=server.arg("State").charAt(0);
}
Malagath:
But when I try to implement the same thing straight on the wifi development board, it gives an error for not being able to read the Argument data to an integer. Because the argument data is a string.
So the return value of your server.arg("State") is String. This is quite different from c-strings, which essentially consists of an array of char's. And yes, there is no implicit conversion for String to int.
Malagath:
So I read a lot of different things about it but to no end. (Maybe I've been searching for the wrong thing.)
Tried the basics atoi(); -functions and such. But I think I read somewhere the string has to start with a number or it will just give '0' as it did.
atoi() operates on char-arrays, not String objects.
Malagath:
So more researching and I think I hit the core of the problem. The wifi board sends the data straight to the serial port with Serial.println. (Which outputs the data as human readable ascii).
So I think the serial connection changes the data type to a format that can be read into an integer and used as such. (Stores the ascii letter as ascii character into an integer).
Not quite. The serial peripheral will send the data in bytes. So before sending anything, it has to be deserialized into a byte-array (same as char-array). On the receiver side, Serial.read() gives you a single character, which is of type char. This is also why you can switch on it, because a char is just another byte-value. It holds a number between 0 and 255 (for unsigned char's), only by defintion it is interpreted as a character (see ASCII-table).
Malagath:
And the six cent question: How to change this type directly on the code of the wifi development board? Or am I better of using another format?
Try this:
char firstCharacter = server.arg("State")[0];
PieterP:
Post the full code and error messages.
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
const char *host = "WiFi_Robot_NodeMCU";
const char *ssid = "WiFi_Robot";
const char *password = "mywifipassword";
ESP8266WebServer server(80);
#include <Servo.h>
Servo myservo;
int servoLL = 180;
int servoL = 140;
int servoS = 90;
int servoR = 40;
int servoRR = 0;
const int ledpin = 16; // D0
const int motor1 = 5; // D1
const int motor2 = 4; // D2
const int motorpwm = 0; // D3
int command;
boolean lightFront = false;
void setup() {
pinMode(ledpin, OUTPUT);
pinMode(motor1, OUTPUT);
pinMode(motor2, OUTPUT);
pinMode(motorpwm, OUTPUT);
myservo.attach(2); // D4
Serial.begin(115200);
WiFi.mode(WIFI_AP);
WiFi.softAP(ssid, password);
server.on ( "/", HTTP_handleRoot );
server.onNotFound ( HTTP_handleRoot );
server.begin();
}
void loop() {
server.handleClient();
delay(50);
}
void HTTP_handleRoot(void) {
if( server.hasArg("State") ){
command = server.arg("State");
if (lightFront) {digitalWrite(ledpin, HIGH);}
if (!lightFront) {digitalWrite(ledpin, LOW);}
switch (command) {
case 'S':stopRobot();break;
case 'A':LL2();break;
case 'B':L2();break;
case 'C':F2();break;
case 'D':R2();break;
case 'E':RR2();break;
case 'F':LL1();break;
case 'G':L1();break;
case 'H':F1();break;
case 'I':R1();break;
case 'J':RR1();break;
case 'K':LLB();break;
case 'L':LB();break;
case 'M':B();break;
case 'N':RB();break;
case 'O':RRB();break;
case 'W':lightFront = true;break;
case 'w':lightFront = false;break;
}
}
server.send ( 200, "text/html", "" );
}
This was basically the first thing I tried. Gives the following error:
legorobot:48:13: error: cannot convert 'String' to 'int' in assignment
command = server.arg("State");
^
exit status 1
cannot convert 'String' to 'int' in assignment
PieterP:
As a side note: why are you using HTTP to send a single byte? It's a huge waste of resources.
This was the best working solution I found for this application. And the coding is pretty simple and non-complicated. And I can actually modify the android app myself with MIT App Inventor.
(I'm more of a hardware electronics person than a coder.)
LightuC:
Try this:
char firstCharacter = server.arg("State")[0];
Thanks a ton! Seems to work on premilinary testing with a led instead of motors. 
On the side note. Can you elaborate what's the meaning of that ' [ 0 ] ' in 'server.arg("State")[0];'?
Malagath:
On the side note. Can you elaborate what's the meaning of that ' [ 0 ] ' in 'server.arg("State")[0];'?
the same as .charAt(0), the character residing at location '0' within the String.